Documentation
¶
Overview ¶
Package amplifi controls Ubiquiti AmpliFi routers and mesh points over their local control protocol, the same one the AmpliFi phone app uses on the LAN. No cloud account is involved.
A unit is any AmpliFi box. The router is the unit connected to the internet; mesh points are the others.
This package holds the session: Dial logs in with the admin password and returns an encrypted Client. The functional areas live in their own packages, which take the client as their second argument:
c, err := amplifi.Dial(ctx, "192.0.2.10", password)
if err != nil {
return err
}
defer c.Close()
board, err := device.GetBoard(ctx, c)
peers, err := mesh.Peers(ctx, c)
cfg, err := wifi.GetConfig(ctx, c)
The area packages are device, mesh, clients, wifi, network, dhcp, portforward, access, teleport, firmware and system; discovery finds units on the LAN. Client.Call, CallJSON and Property reach any method directly, and Client.Events streams the events the unit pushes.
The wire protocol is a WebSocket on port 9016 carrying AllJoyn-style JSON method calls, authenticated with SRP-6a and encrypted with libsodium's secretstream construction.
Units use self-signed TLS certificates, so the certificate chain is not verified. To detect a replaced or impersonated unit, save Client.CertificateFingerprint after the first login and pass it to later dials with WithCertificateFingerprint.
Index ¶
- Constants
- Variables
- func IsRouterError(err error) bool
- type CertificateMismatchError
- type Client
- func (c *Client) Call(ctx context.Context, iface, method string, arg any) (any, error)
- func (c *Client) CallDisconnecting(ctx context.Context, iface, method string, arg any) error
- func (c *Client) CallJSON(ctx context.Context, iface, method string, arg any) (any, error)
- func (c *Client) CertificateFingerprint() string
- func (c *Client) Close() error
- func (c *Client) Events(ctx context.Context) iter.Seq2[Event, error]
- func (c *Client) PasswordHash() []byte
- func (c *Client) Property(ctx context.Context, iface, name string) (any, error)
- func (c *Client) SetProperty(ctx context.Context, iface, name string, value any) error
- func (c *Client) Ubus(ctx context.Context, path, method string, args map[string]any) (any, error)
- type Event
- type MAC
- type Option
- type RawMsgpack
- type Role
- type RouterError
Constants ¶
const ( IfaceDevice = "Device" IfaceClusterNode = "ClusterNode" IfaceFwUpdate = "FwUpdate" IfaceMagicLink = "MagicLink" IfaceUnsecure = "Unsecure" )
Interface names accepted by Call, CallJSON, Property and SetProperty. The short names expand to the full com.ubnt.UnifiHome.* form.
const Port = 9016
Port is the TCP port the control WebSocket listens on, on the router and on every mesh point.
Variables ¶
var ErrAuth = errors.New("authentication failed")
ErrAuth is returned by Dial when the router rejects the login, typically because the password is wrong. Test for it with errors.Is.
Functions ¶
func IsRouterError ¶
IsRouterError reports whether err is, or wraps, a RouterError: the router understood the request and refused it, as opposed to a transport failure.
Types ¶
type CertificateMismatchError ¶
CertificateMismatchError is returned by Dial when the unit's certificate does not have the fingerprint given with WithCertificateFingerprint. Test for it with errors.As.
func (*CertificateMismatchError) Error ¶
func (e *CertificateMismatchError) Error() string
Error formats the error with both fingerprints.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an authenticated, encrypted control session with one unit. It is not safe for concurrent use.
func Dial ¶
Dial connects to the unit at host, logs in with the admin password and switches the session to encrypted framing. The certificate chain is not verified because units use self-signed certificates; see WithCertificateFingerprint.
func DialWithHash ¶
DialWithHash is Dial with a password hash from Client.PasswordHash instead of the password. It fails with ErrAuth if the password has since changed or host is a different unit.
func (*Client) Call ¶
Call invokes any method with a msgpack argument and returns the decoded result. It is the escape hatch for methods without a typed wrapper.
In arg, map[string]any keys that are decimal numbers become integer option codes and []byte becomes binary. A nil arg sends no argument. Raw msgpack can be passed as RawMsgpack. The result is a decoded msgpack value (maps are map[string]any keyed as described for Event.Payload) or, for methods that answer in JSON, the JSON value.
func (*Client) CallDisconnecting ¶
CallDisconnecting invokes a method after which the unit may drop the connection instead of replying, such as Reboot or FactoryReset. Once the request is sent, a closed connection or no reply within a few seconds counts as success, since a unit going down may do either; a router error in a reply is returned. The session is unusable afterwards.
func (*Client) CertificateFingerprint ¶
CertificateFingerprint returns the fingerprint of the unit's TLS certificate in the format SSH uses: "SHA256:" followed by the unpadded base64 SHA-256 digest of the certificate's DER encoding.
func (*Client) Events ¶
Events streams the unit's events until ctx is done, keeping the session alive with periodic pings. Iteration ends with a non-nil error if the connection fails or the unit stops answering pings, and silently when ctx is done. The session must not be used for calls while iterating.
func (*Client) PasswordHash ¶
PasswordHash returns the hash this session logged in with. It lets DialWithHash log in to the same unit later without the password. The hash cannot be turned back into the password, but it grants the same access, so store it as carefully as the password itself.
func (*Client) SetProperty ¶
SetProperty writes a property.
type Event ¶
type Event struct {
Time time.Time
Interface string // e.g. "ClusterNode"
Name string // e.g. "ClientMacDiscovered"
// Payload is the decoded payload: a JSON value or a decoded msgpack
// value, or nil if the event carries none. In msgpack payloads binary
// values are []byte, and binary map keys are strings of the raw bytes.
Payload any
}
Event is a message the unit pushes on its own, such as a client joining (ClusterNode.ClientMacDiscovered) or a configuration change (ClusterNode.WifiConfigChanged). The protocol calls these signals.
type MAC ¶
type MAC net.HardwareAddr
MAC is a hardware address. Unlike net.HardwareAddr it encodes as the usual colon-separated string in JSON and other text formats.
func (MAC) MarshalText ¶
MarshalText implements encoding.TextMarshaler.
func (*MAC) UnmarshalText ¶
UnmarshalText implements encoding.TextUnmarshaler. Empty text yields an empty MAC.
type Option ¶
type Option func(*Client)
Option configures Dial.
func WithCertificateFingerprint ¶
WithCertificateFingerprint makes Dial fail with a CertificateMismatchError, before sending anything, unless the unit's TLS certificate has fingerprint fp, in the format of Client.CertificateFingerprint.
func WithLogger ¶
WithLogger sets the logger used for protocol tracing. The default discards all output.
type RawMsgpack ¶
type RawMsgpack []byte
RawMsgpack is an already encoded msgpack argument for Call.
type RouterError ¶
RouterError is an error reported by the router in a response's payload.error. Test for it with errors.As.
func (*RouterError) Error ¶
func (e *RouterError) Error() string
Error formats the error as "router error <code>: <msg>".
Directories
¶
| Path | Synopsis |
|---|---|
|
Package access manages scheduled access control, the app's parental controls.
|
Package access manages scheduled access control, the app's parental controls. |
|
Package clients covers the clients on the network: the mesh's current and historic client lists, Wi-Fi association details and signal quality, client counts, custom client settings (name, pause), fingerprints and the guest Wi-Fi whitelist.
|
Package clients covers the clients on the network: the mesh's current and historic client lists, Wi-Fi association details and signal quality, client counts, custom client settings (name, pause), fingerprints and the guest Wi-Fi whitelist. |
|
cmd
|
|
|
amplifi
command
Command amplifi inspects and controls AmpliFi routers from the command line.
|
Command amplifi inspects and controls AmpliFi routers from the command line. |
|
Package device reads and changes the state of the unit a session is connected to: its board, running firmware, throughput, internet check, MAC addresses, identity configuration, properties and display settings, and reboots, upgrades or factory resets it.
|
Package device reads and changes the state of the unit a session is connected to: its board, running firmware, throughput, internet check, MAC addresses, identity configuration, properties and display settings, and reboots, upgrades or factory resets it. |
|
Package dhcp reads and changes a unit's DHCP server: the address pools of each network and the static leases (address reservations).
|
Package dhcp reads and changes a unit's DHCP server: the address pools of each network and the static leases (address reservations). |
|
Package discovery finds AmpliFi units on the local network using the Ubiquiti UDP discovery protocol on port 10001.
|
Package discovery finds AmpliFi units on the local network using the Ubiquiti UDP discovery protocol on port 10001. |
|
Package firmware checks for and installs firmware upgrades across an AmpliFi mesh (the FwUpdate interface), reports their progress, and reads and writes the automatic update settings.
|
Package firmware checks for and installs firmware upgrades across an AmpliFi mesh (the FwUpdate interface), reports their progress, and reads and writes the automatic update settings. |
|
internal
|
|
|
appinfo
Package appinfo holds build information injected at link time with -ldflags "-X github.com/borud/amplifi/internal/appinfo.Version=...".
|
Package appinfo holds build information injected at link time with -ldflags "-X github.com/borud/amplifi/internal/appinfo.Version=...". |
|
cli
Package cli implements the amplifi command-line interface.
|
Package cli implements the amplifi command-line interface. |
|
creds
Package creds stores saved logins for the CLI so the admin password is entered once per unit.
|
Package creds stores saved logins for the CLI so the admin password is entered once per unit. |
|
rpc
Package rpc holds the helpers the area packages (device, wifi, clients, ...) share on top of amplifi.Client's public Call and CallJSON: typed result decoding, read-modify-write setters, and access to the integer-keyed option maps the Device and ClusterNode interfaces use.
|
Package rpc holds the helpers the area packages (device, wifi, clients, ...) share on top of amplifi.Client's public Call and CallJSON: typed result decoding, read-modify-write setters, and access to the integer-keyed option maps the Device and ClusterNode interfaces use. |
|
secretstream
Package secretstream frames and encrypts AmpliFi control messages with crypto_secretstream_xchacha20poly1305, matching the app's EncryptionHelper (libsodium via lazysodium) byte-for-byte.
|
Package secretstream frames and encrypts AmpliFi control messages with crypto_secretstream_xchacha20poly1305, matching the app's EncryptionHelper (libsodium via lazysodium) byte-for-byte. |
|
srp
Package srp implements the client side of the AmpliFi SRP-6a login: the RFC 5054 2048-bit group with SHA-256 and the app's custom ("csrpcompat") x, client-evidence and server-evidence routines.
|
Package srp implements the client side of the AmpliFi SRP-6a login: the RFC 5054 2048-bit group with SHA-256 and the app's custom ("csrpcompat") x, client-evidence and server-evidence routines. |
|
wire
Package wire defines the JSON envelopes exchanged on the AmpliFi control WebSocket.
|
Package wire defines the JSON envelopes exchanged on the AmpliFi control WebSocket. |
|
Package mesh covers the units that make up the mesh: the connected mesh points, every registered unit, backhaul signal quality, the Ethernet ports of every unit, factory pairing of new mesh points, and ignoring or factory resetting units.
|
Package mesh covers the units that make up the mesh: the connected mesh points, every registered unit, backhaul signal quality, the Ethernet ports of every unit, factory pairing of new mesh points, and ignoring or factory resetting units. |
|
Package network reads and changes a unit's IP networking: the WAN and LAN configuration, the logical network interfaces, UPnP/NAT-PMP and QoS. The DHCP server and port forwarding are in packages dhcp and portforward.
|
Package network reads and changes a unit's IP networking: the WAN and LAN configuration, the logical network interfaces, UPnP/NAT-PMP and QoS. The DHCP server and port forwarding are in packages dhcp and portforward. |
|
Package portforward reads and changes a unit's port forwarding rules.
|
Package portforward reads and changes a unit's port forwarding rules. |
|
Package system covers the mesh-wide and unit-level maintenance functions of an AmpliFi mesh: the site configuration, the admin password, the internet speed test, iperf, support bundles, statistics and HomeKit.
|
Package system covers the mesh-wide and unit-level maintenance functions of an AmpliFi mesh: the site configuration, the admin password, the internet speed test, iperf, support bundles, statistics and HomeKit. |
|
Package teleport controls Teleport, AmpliFi's remote access VPN, through the router's MagicLink interface: connectivity, invite codes and the clients that have joined.
|
Package teleport controls Teleport, AmpliFi's remote access VPN, through the router's MagicLink interface: connectivity, invite codes and the clients that have joined. |
|
Package wifi reads and changes a unit's Wi-Fi: the main, guest and IoT networks, radios and interfaces, channels and countries, DFS radar events, the signal quality scan and WPS push-button pairing.
|
Package wifi reads and changes a unit's Wi-Fi: the main, guest and IoT networks, radios and interfaces, channels and countries, DFS radar events, the signal quality scan and WPS push-button pairing. |