Documentation
¶
Overview ¶
Package wgnet implements a WireGuard point-to-point endpoint library.
Unlike the standard WireGuard implementation which is designed for multipoint networks, wgnet focuses on simple client/server endpoint connections.
Index ¶
- Constants
- type Config
- type Handler
- func (h *Handler) AcceptUnknownPeer(peerKey NoisePublicKey, initiationPacket []byte, remoteAddr *net.UDPAddr) error
- func (h *Handler) AddPeer(peerKey NoisePublicKey)
- func (h *Handler) AddPeerWithPSK(peerKey NoisePublicKey, psk NoisePresharedKey)
- func (h *Handler) Close() error
- func (h *Handler) Encrypt(data []byte, peerKey NoisePublicKey) ([]byte, error)
- func (h *Handler) GenerateKeepalive(peerKey NoisePublicKey) ([]byte, error)
- func (h *Handler) GetPeerInfo(peerKey NoisePublicKey) (PeerInfo, bool)
- func (h *Handler) HasSession(peerKey NoisePublicKey) bool
- func (h *Handler) InitiateHandshake(peerKey NoisePublicKey) ([]byte, error)
- func (h *Handler) IsAuthorizedPeer(peerKey NoisePublicKey) bool
- func (h *Handler) Maintenance()
- func (h *Handler) Peers() []NoisePublicKey
- func (h *Handler) ProcessPacket(data []byte, remoteAddr *net.UDPAddr) (*PacketResult, error)
- func (h *Handler) PublicKey() NoisePublicKey
- func (h *Handler) RemovePeer(peerKey NoisePublicKey)
- func (h *Handler) SessionInfo(peerKey NoisePublicKey) (lastReceived, lastSent time.Time, ok bool)
- func (h *Handler) SetPeerExpiry(peerKey NoisePublicKey, expiresAt time.Time)
- type MultiHandler
- func (mh *MultiHandler) AddHandler(h *Handler) error
- func (mh *MultiHandler) Close() error
- func (mh *MultiHandler) Handler(pubKey NoisePublicKey) *Handler
- func (mh *MultiHandler) Handlers() []*Handler
- func (mh *MultiHandler) Maintenance()
- func (mh *MultiHandler) ProcessPacket(data []byte, remoteAddr *net.UDPAddr) (*MultiPacketResult, error)
- func (mh *MultiHandler) RemoveHandler(pubKey NoisePublicKey) *Handler
- type MultiPacketResult
- type NoisePresharedKey
- type NoisePrivateKey
- type NoisePublicKey
- type PacketResult
- type PacketType
- type PeerInfo
- type Server
- func (s *Server) Close() error
- func (s *Server) Connect(peerKey NoisePublicKey, addr *net.UDPAddr) error
- func (s *Server) ConnectWith(peerKey NoisePublicKey, addr *net.UDPAddr, handler *Handler) error
- func (s *Server) PeerAddr(peerKey NoisePublicKey) *net.UDPAddr
- func (s *Server) Send(data []byte, peerKey NoisePublicKey) error
- func (s *Server) SendTo(data []byte, peerKey NoisePublicKey, handler *Handler) error
- func (s *Server) Serve(conn net.PacketConn) error
- type ServerConfig
- type UnknownPeerFunc
Constants ¶
const ( // CookieRefreshTime is the maximum lifetime of a cookie secret. CookieRefreshTime = 120 * time.Second // RejectAfterTime is how long sessions and pending handshakes are kept // before being cleaned up by Maintenance. RejectAfterTime = 180 * time.Second // Key sizes NoisePublicKeySize = 32 NoisePrivateKeySize = 32 // WindowSize is the size of the replay protection sliding window. WindowSize = 8192 )
WireGuard protocol constants
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// PrivateKey is the local static private key. If zero, a new key is generated.
PrivateKey NoisePrivateKey
// Conn is the UDP connection used for sending handshake responses when
// AcceptUnknownPeer is called. Required if OnUnknownPeer is set.
Conn net.PacketConn
// OnUnknownPeer is called when a handshake arrives from an unauthorized peer.
// If nil, unknown peers are rejected.
OnUnknownPeer UnknownPeerFunc
}
Config configures a Handler.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler implements the WireGuard protocol, supporting both initiator and responder roles. Use InitiateHandshake to start a connection, or pass incoming packets to ProcessPacket to respond to them.
func NewHandler ¶
NewHandler creates a new WireGuard protocol handler.
func (*Handler) AcceptUnknownPeer ¶ added in v0.1.1
func (h *Handler) AcceptUnknownPeer(peerKey NoisePublicKey, initiationPacket []byte, remoteAddr *net.UDPAddr) error
AcceptUnknownPeer authorizes a previously unknown peer, re-processes its handshake initiation packet, and sends the handshake response via the handler's connection. Call this from an OnUnknownPeer callback (or later) after verifying the peer.
func (*Handler) AddPeer ¶
func (h *Handler) AddPeer(peerKey NoisePublicKey)
AddPeer authorizes a peer by public key.
func (*Handler) AddPeerWithPSK ¶
func (h *Handler) AddPeerWithPSK(peerKey NoisePublicKey, psk NoisePresharedKey)
AddPeerWithPSK authorizes a peer with a preshared key.
func (*Handler) Close ¶
Close clears all pending handshakes, sessions, and keypairs. It does not affect peer authorization — peers remain in the authorized list.
func (*Handler) Encrypt ¶
func (h *Handler) Encrypt(data []byte, peerKey NoisePublicKey) ([]byte, error)
Encrypt encrypts data for transmission to a peer.
func (*Handler) GenerateKeepalive ¶
func (h *Handler) GenerateKeepalive(peerKey NoisePublicKey) ([]byte, error)
GenerateKeepalive generates a keepalive packet for a peer.
func (*Handler) GetPeerInfo ¶ added in v0.1.4
func (h *Handler) GetPeerInfo(peerKey NoisePublicKey) (PeerInfo, bool)
GetPeerInfo returns information about an authorized peer. Returns false if the peer is not found.
func (*Handler) HasSession ¶
func (h *Handler) HasSession(peerKey NoisePublicKey) bool
HasSession returns true if there is an active session with the given peer.
func (*Handler) InitiateHandshake ¶
func (h *Handler) InitiateHandshake(peerKey NoisePublicKey) ([]byte, error)
InitiateHandshake creates a handshake initiation packet for the given peer. The peer must already be authorized via AddPeer or AddPeerWithPSK. Returns a 148-byte packet ready to send.
func (*Handler) IsAuthorizedPeer ¶
func (h *Handler) IsAuthorizedPeer(peerKey NoisePublicKey) bool
IsAuthorizedPeer checks if a peer's public key is authorized. Returns false if the peer is unknown or has passed its ExpiresAt time.
func (*Handler) Maintenance ¶
func (h *Handler) Maintenance()
Maintenance performs periodic cleanup: rotates the cookie secret, removes stale pending handshakes, and expires inactive sessions. Call this periodically (e.g. every 10s). The Server calls it automatically.
func (*Handler) Peers ¶
func (h *Handler) Peers() []NoisePublicKey
Peers returns the list of authorized peer public keys.
func (*Handler) ProcessPacket ¶
ProcessPacket processes an incoming WireGuard packet and returns the result. It dispatches by message type: initiation (1), response (2), cookie reply (3), and transport data (4). The caller is responsible for sending any Response bytes back to remoteAddr.
func (*Handler) PublicKey ¶
func (h *Handler) PublicKey() NoisePublicKey
PublicKey returns the handler's public key.
func (*Handler) RemovePeer ¶
func (h *Handler) RemovePeer(peerKey NoisePublicKey)
RemovePeer removes a peer from the authorized list and tears down its session.
func (*Handler) SessionInfo ¶
func (h *Handler) SessionInfo(peerKey NoisePublicKey) (lastReceived, lastSent time.Time, ok bool)
SessionInfo returns timing information about a peer's session. Returns zero times if no session exists.
func (*Handler) SetPeerExpiry ¶
func (h *Handler) SetPeerExpiry(peerKey NoisePublicKey, expiresAt time.Time)
SetPeerExpiry sets an expiration time for a peer. After this time, the peer will no longer be authorized for new handshakes.
type MultiHandler ¶
type MultiHandler struct {
// contains filtered or unexported fields
}
MultiHandler multiplexes multiple Handler instances on a single UDP port. It routes incoming packets to the correct handler based on MAC1 (for initiation messages), pending handshake index (for responses and cookie replies), or keypair index (for transport data).
func NewMultiHandler ¶
func NewMultiHandler(handlers ...*Handler) (*MultiHandler, error)
NewMultiHandler creates a MultiHandler from one or more handlers. Returns an error if no handlers are provided or if duplicate public keys are detected.
func (*MultiHandler) AddHandler ¶
func (mh *MultiHandler) AddHandler(h *Handler) error
AddHandler adds a handler to the MultiHandler. Returns an error if a handler with the same public key already exists.
func (*MultiHandler) Close ¶
func (mh *MultiHandler) Close() error
Close closes all handlers, returning the first error encountered.
func (*MultiHandler) Handler ¶
func (mh *MultiHandler) Handler(pubKey NoisePublicKey) *Handler
Handler returns the handler with the given public key, or nil if not found.
func (*MultiHandler) Handlers ¶
func (mh *MultiHandler) Handlers() []*Handler
Handlers returns a snapshot of all handlers.
func (*MultiHandler) Maintenance ¶
func (mh *MultiHandler) Maintenance()
Maintenance calls Maintenance on all handlers.
func (*MultiHandler) ProcessPacket ¶
func (mh *MultiHandler) ProcessPacket(data []byte, remoteAddr *net.UDPAddr) (*MultiPacketResult, error)
ProcessPacket routes an incoming packet to the correct handler and processes it.
For handshake initiation (type 1): iterates handlers and checks MAC1 against each. For handshake response (type 2) and cookie reply (type 3): extracts the receiver index and checks pending handshake ownership. For transport data (type 4): extracts the receiver index and checks keypair ownership. Other message types return an error.
func (*MultiHandler) RemoveHandler ¶
func (mh *MultiHandler) RemoveHandler(pubKey NoisePublicKey) *Handler
RemoveHandler removes and returns the handler with the given public key. Returns nil if no handler matches.
type MultiPacketResult ¶
type MultiPacketResult struct {
*PacketResult
Handler *Handler // which identity processed the packet
}
MultiPacketResult extends PacketResult with the handler that processed the packet.
type NoisePresharedKey ¶
type NoisePresharedKey [32]byte
NoisePresharedKey is a WireGuard preshared key.
func (NoisePresharedKey) MarshalText ¶ added in v0.1.4
func (psk NoisePresharedKey) MarshalText() ([]byte, error)
MarshalText implements encoding.TextMarshaler.
func (NoisePresharedKey) String ¶ added in v0.1.4
func (psk NoisePresharedKey) String() string
String returns the base64-encoded preshared key.
func (*NoisePresharedKey) UnmarshalText ¶ added in v0.1.4
func (psk *NoisePresharedKey) UnmarshalText(text []byte) error
UnmarshalText implements encoding.TextUnmarshaler.
type NoisePrivateKey ¶
type NoisePrivateKey [32]byte
NoisePrivateKey is a Curve25519 private key.
func GeneratePrivateKey ¶
func GeneratePrivateKey() (NoisePrivateKey, error)
GeneratePrivateKey generates a new random Curve25519 private key.
func (NoisePrivateKey) MarshalText ¶ added in v0.1.4
func (sk NoisePrivateKey) MarshalText() ([]byte, error)
MarshalText implements encoding.TextMarshaler.
func (NoisePrivateKey) PublicKey ¶
func (sk NoisePrivateKey) PublicKey() NoisePublicKey
PublicKey derives the public key from this private key.
func (NoisePrivateKey) String ¶ added in v0.1.4
func (sk NoisePrivateKey) String() string
String returns the base64-encoded private key.
func (*NoisePrivateKey) UnmarshalText ¶ added in v0.1.4
func (sk *NoisePrivateKey) UnmarshalText(text []byte) error
UnmarshalText implements encoding.TextUnmarshaler.
type NoisePublicKey ¶
type NoisePublicKey [32]byte
NoisePublicKey is a Curve25519 public key.
func (NoisePublicKey) MarshalText ¶ added in v0.1.4
func (pk NoisePublicKey) MarshalText() ([]byte, error)
MarshalText implements encoding.TextMarshaler.
func (NoisePublicKey) String ¶ added in v0.1.4
func (pk NoisePublicKey) String() string
String returns the base64-encoded public key (WireGuard standard encoding).
func (*NoisePublicKey) UnmarshalText ¶ added in v0.1.4
func (pk *NoisePublicKey) UnmarshalText(text []byte) error
UnmarshalText implements encoding.TextUnmarshaler.
type PacketResult ¶
type PacketResult struct {
// Type indicates what kind of result this is.
Type PacketType
// Response contains bytes to send back to the remote address (handshake or cookie reply).
Response []byte
// Data contains decrypted plaintext (transport data).
Data []byte
// PeerKey is the public key of the peer.
PeerKey NoisePublicKey
}
PacketResult is the result of processing an incoming packet.
type PacketType ¶
type PacketType int
PacketType indicates the type of a processed packet result.
const ( // PacketHandshakeResponse indicates a completed handshake with response bytes // that should be sent back. On the responder side this is the handshake response // message; on the initiator side it is a keepalive confirming the session. PacketHandshakeResponse PacketType = iota // PacketCookieReply indicates a cookie reply that should be sent back. PacketCookieReply // PacketTransportData indicates decrypted transport data. PacketTransportData // PacketKeepalive indicates a keepalive (empty transport data). PacketKeepalive // PacketCookieReceived indicates a cookie reply was received and stored // internally. No action is required; retry the handshake initiation. PacketCookieReceived )
type PeerInfo ¶
type PeerInfo struct {
PublicKey NoisePublicKey
HasPSK bool
CreatedAt time.Time
ExpiresAt time.Time
LastHandshake time.Time
}
PeerInfo contains information about an authorized peer.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server manages a WireGuard endpoint over a net.PacketConn, handling the read loop, automatic protocol responses, and periodic maintenance.
func NewServer ¶
func NewServer(cfg ServerConfig) (*Server, error)
NewServer creates a Server from the given configuration.
func (*Server) Close ¶
Close stops the server's read loop and maintenance goroutines. It does not close the net.PacketConn or the handler(s) — the caller owns those.
Note: Close sets a read deadline on the connection to unblock any pending ReadFrom call. The caller should reset the deadline if reusing the connection.
func (*Server) Connect ¶
func (s *Server) Connect(peerKey NoisePublicKey, addr *net.UDPAddr) error
Connect initiates a handshake to a peer at the given address. In single-handler mode, uses the handler. In multi-handler mode, returns an error (use ConnectWith to specify the handler).
func (*Server) ConnectWith ¶
ConnectWith initiates a handshake to a peer using the specified handler.
func (*Server) PeerAddr ¶
func (s *Server) PeerAddr(peerKey NoisePublicKey) *net.UDPAddr
PeerAddr returns the last known UDP address for the given peer, or nil if the peer has not been seen.
func (*Server) Send ¶
func (s *Server) Send(data []byte, peerKey NoisePublicKey) error
Send encrypts data and sends it to the given peer. In multi-handler mode the handler is chosen automatically based on which handler completed the peer's handshake. Use SendTo to specify the handler explicitly.
type ServerConfig ¶
type ServerConfig struct {
// Handler provides a single WireGuard identity.
// Mutually exclusive with MultiHandler.
Handler *Handler
// MultiHandler provides multiple WireGuard identities.
// Mutually exclusive with Handler.
MultiHandler *MultiHandler
// OnPacket is called when decrypted transport data arrives. The handler
// argument identifies which identity processed the packet (always the
// same pointer in single-handler mode).
OnPacket func(data []byte, peerKey NoisePublicKey, handler *Handler)
// OnPeerConnected is called when a new handshake completes. Optional.
OnPeerConnected func(peerKey NoisePublicKey, handler *Handler)
// MaintenanceInterval controls how often handler maintenance runs.
// Default: 10s.
MaintenanceInterval time.Duration
// ReadBufferSize is the size of the UDP read buffer. Default: 2048.
ReadBufferSize int
}
ServerConfig configures a Server.
type UnknownPeerFunc ¶
type UnknownPeerFunc func(publicKey NoisePublicKey, remoteAddr *net.UDPAddr, packet []byte)
UnknownPeerFunc is called when a handshake is received from an unknown peer. The packet slice is only valid for the duration of the call — the callback must copy it before returning if it needs to keep the data (e.g. to pass to AcceptUnknownPeer asynchronously). To accept the peer, call Handler.AcceptUnknownPeer with the peer key, copied packet, and remote address; it re-processes the handshake and sends the response via the handler's Conn.