Documentation
¶
Overview ¶
Package vpn is the top-level go-openlawsvpn package.
It provides a high-level OpenVPN3 client that handles the full connection lifecycle including SAML/CRV1 authentication for AWS Client VPN and standard certificate-based auth for other OpenVPN3 servers.
Typical usage:
p, err := profile.ParseFile(f)
c := vpn.New(p)
c.SAMLTokenFn = func(ctx context.Context, ch vpn.SAMLChallenge) (string, error) {
// open ch.URL in a browser, return the SAMLResponse token
}
err = c.Connect(ctx)
// tunnel is now up; data flows through the TUN device
c.Disconnect()
c.WaitForDisconnect()
Index ¶
- Constants
- Variables
- type Client
- func (c *Client) Connect(ctx context.Context) error
- func (c *Client) ConnectPhase2(ctx context.Context, samlToken string) error
- func (c *Client) ConnectPhase2Reuse(ctx context.Context, samlToken string) error
- func (c *Client) Disconnect() error
- func (c *Client) Done() <-chan struct{}
- func (c *Client) LocalIP() string
- func (c *Client) Phase1ForTest(ctx context.Context) (*SAMLChallenge, error)
- func (c *Client) Phase1IP() string
- func (c *Client) Reconnect(ctx context.Context) error
- func (c *Client) ResetForTest(challenge *SAMLChallenge)
- func (c *Client) SetRelayPhase2(remoteIP, stateID string)
- func (c *Client) Stats() Stats
- func (c *Client) WaitForDisconnect() error
- type ClientState
- type Event
- type EventFn
- type EventType
- type SAMLChallenge
- type Stats
Constants ¶
const AWSSAMLUnsupportedNotice = "This client is not AWS-supported for SAML Client VPN authentication. For AWS-supported operation, use the AWS VPN Client."
AWSSAMLUnsupportedNotice describes the AWS support boundary for this independent CRV1 implementation.
Variables ¶
var ErrReauthRequired = fmt.Errorf("vpn: SAML re-authentication required: token rejected by server")
ErrReauthRequired is returned by Reconnect when the cached SAML token has been rejected by the server (AUTH_FAILED). The SAML assertion is cryptographically bound to its original AuthnRequest and cannot be reused with a new Phase 1 session. The caller must run the full browser flow again.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// SAMLTokenFn is called during Connect when the server issues a SAML/CRV1
// challenge. The callback must open challenge.URL in a browser, wait for
// the SAMLResponse via the ACS server on 127.0.0.1:35001, and return the
// base64-encoded token. Required for AWS Client VPN profiles; ignored for
// certificate-based auth.
SAMLTokenFn func(ctx context.Context, challenge SAMLChallenge) (string, error)
// ProtectFn, if set, is called with the raw file descriptor of every
// transport socket before it is used. On Android this must call
// VpnService.protect(fd) so the socket bypasses the VPN tunnel and
// reaches the real network. Nil on Linux desktop (no-op).
ProtectFn func(fd int) error
// TUNSetup, if set, is called instead of tun.Open() to obtain the TUN
// device. The callback receives the ifconfig JSON so the Android layer can
// configure VpnService.Builder before calling establish().
// Nil on Linux desktop — tun.Open() is used directly.
TUNSetup func(ifconfigJSON string, mtu int) (*tun.Device, error)
// EventFn, if set, is called for every notable lifecycle event: state
// transitions, log lines, and periodic stats. Called from internal
// goroutines — must not block. Set before calling Connect.
EventFn EventFn
// reconnect
// MaxReconnects is the maximum number of reconnect attempts before giving
// up. A value of 0 means unlimited retries. Default is 0 (unlimited).
MaxReconnects int
// contains filtered or unexported fields
}
Client is a go-openlawsvpn VPN client.
A Client is not safe for concurrent use by multiple goroutines except where noted (Stats and Wait may be called concurrently with the data channel).
func New ¶
New creates a new Client from the given profile. The Client is idle until Connect is called.
func (*Client) Connect ¶
Connect dials, authenticates, and brings up the VPN tunnel.
The auth flow is auto-detected from the profile:
- AWS Client VPN (cvpn-endpoint-*.amazonaws.com): SAML/CRV1 two-phase flow. SAMLTokenFn must be set; it is called with the challenge URL and must return the base64-encoded SAMLResponse.
- Certificate auth (profile has <cert>+<key>): mutual-TLS, no SAML.
- Fallback: plain connection (PUSH_REPLY expected without challenge).
Connect is not safe for concurrent use.
func (*Client) ConnectPhase2 ¶
ConnectPhase2 completes the VPN connection using a SAML token delivered via the relay server. Call SetRelayPhase2 first to pre-seed Phase 1 state.
samlToken is the base64-encoded SAMLResponse received from the relay.
func (*Client) ConnectPhase2Reuse ¶
ConnectPhase2Reuse completes the VPN connection with an already-obtained SAML token. Only for testing token-reuse behaviour — do not use in production code. Call ResetForTest first to restore the required state.
func (*Client) Disconnect ¶
Disconnect initiates a graceful teardown of the VPN tunnel. It signals the background goroutines to stop and begins cleaning up. Call Wait to block until teardown completes.
func (*Client) Done ¶
func (c *Client) Done() <-chan struct{}
Done returns a channel that is closed when the client disconnects (for any reason — graceful, keepalive timeout, server-initiated, etc.). The disconnect reason is available via Wait after the channel closes.
func (*Client) LocalIP ¶
LocalIP returns the tunnel-side IP address assigned by the server after a successful Phase 2, or "" if the tunnel is not up.
func (*Client) Phase1ForTest ¶
func (c *Client) Phase1ForTest(ctx context.Context) (*SAMLChallenge, error)
Phase1ForTest runs connectPhase1 and returns the SAML challenge (or nil). Only for integration tests — do not use in production code.
func (*Client) Phase1IP ¶
Phase1IP returns the sticky backend IP captured during Phase 1. This is the IP the agent must use for Phase 2 to ensure server affinity. Returns "" before Phase 1 completes.
func (*Client) Reconnect ¶
Reconnect tears down the current connection and re-establishes the tunnel.
While the cached SAML token is still valid (NotOnOrAfter not yet passed), Reconnect skips Phase 1 entirely and retries Phase 2 directly with the cached server IP, StateID, and token — no browser required.
If Phase 2 returns AUTH_FAILED (the server's CRV1 session expired during the outage), Reconnect returns ErrReauthRequired immediately. The SAML assertion is bound to the original AuthnRequest ID and cannot be reused with a new Phase 1 session. The caller must run the full browser flow again.
It applies exponential backoff between attempts: 1 s, 2 s, 4 s, … capped at 30 s. MaxReconnects limits total attempts (0 = unlimited, the default).
Reconnect is not safe for concurrent use.
func (*Client) ResetForTest ¶
func (c *Client) ResetForTest(challenge *SAMLChallenge)
ResetForTest resets the client to stateConnecting with the given SAML challenge, so ConnectPhase2Reuse can be called again with the same token. Only for manual token-reuse testing — do not use in production code.
func (*Client) SetRelayPhase2 ¶
SetRelayPhase2 pre-seeds the Phase 1 state obtained by the mobile/desktop app so that ConnectPhase2 can skip Phase 1 and connect directly to the sticky backend IP with the SAML credentials delivered via the relay.
Must be called before ConnectPhase2 and only when using relay mode. remoteIP is the backend server IP from the CRV1 challenge; stateID is the opaque CRV1 state token.
func (*Client) Stats ¶
Stats returns a snapshot of current traffic counters and uptime. Safe to call concurrently while the tunnel is up.
func (*Client) WaitForDisconnect ¶
WaitForDisconnect blocks until the client is fully disconnected and returns the disconnect reason (nil for a clean Disconnect call). It is safe to call WaitForDisconnect concurrently from multiple goroutines.
type ClientState ¶
type ClientState int
ClientState is the connection lifecycle state reported via events.
const ( // StateIdle means no active connection. StateIdle ClientState = iota // StateConnecting covers Phase 1 and Phase 2 establishment. StateConnecting // StateWaitingSAML means Phase 1 completed and the GUI must open the SAML URL. StateWaitingSAML // StateConnected means the TUN interface is up and data flows. StateConnected // StateDisconnecting means teardown is in progress. StateDisconnecting // StateError means connection failed; Message carries the reason. StateError )
func (ClientState) String ¶
func (s ClientState) String() string
String returns a lowercase D-Bus-friendly representation of the state.
type Event ¶
type Event struct {
// Type identifies the event category.
Type EventType
// State is set when Type == EventStateChanged.
State ClientState
// Message carries a log line (EventLog), SAML URL (StateWaitingSAML),
// error description (StateError), or assigned tunnel IP (StateConnected).
Message string
// ServerIP is the VPN server IP (set when State == StateConnected).
ServerIP string
// Stats is set when Type == EventStatsUpdate.
Stats Stats
// At is the wall-clock time of the event.
At time.Time
}
Event is emitted by the Client for every notable lifecycle transition or log line.
type EventFn ¶
type EventFn func(Event)
EventFn is a callback invoked for every Event emitted by the Client. It is called from internal goroutines; implementations must not block. Set Client.EventFn before calling Connect.
type SAMLChallenge ¶
type SAMLChallenge struct {
// URL is the identity-provider URL the user must visit.
URL string
// StateID is the opaque session token that must be returned in Phase 2.
StateID string
}
SAMLChallenge holds the parsed fields from a CRV1 SAML challenge. The caller must open URL in a browser; the IdP will POST the SAMLResponse to 127.0.0.1:35001, which the caller can capture via auth/saml.NewACSServer.
type Stats ¶
type Stats struct {
// BytesSent is the total number of plaintext bytes sent through the tunnel.
BytesSent uint64
// BytesRecv is the total number of plaintext bytes received through the tunnel.
BytesRecv uint64
// Uptime is the duration since the tunnel was established (zero if not up yet).
Uptime time.Duration
}
Stats is a snapshot of per-session traffic counters.
Directories
¶
| Path | Synopsis |
|---|---|
|
auth
|
|
|
saml
Package saml — session expiry monitor.
|
Package saml — session expiry monitor. |
|
cmd
|
|
|
cli
command
Command openlawsvpn-cli is a minimal CLI for the go-openlawsvpn VPN client.
|
Command openlawsvpn-cli is a minimal CLI for the go-openlawsvpn VPN client. |
|
daemon
command
Command openlawsvpn-daemon is a D-Bus system service that manages VPN connections on behalf of the openlawsvpn GTK GUI.
|
Command openlawsvpn-daemon is a D-Bus system service that manages VPN connections on behalf of the openlawsvpn GTK GUI. |
|
relay-server
command
Command relay-server is a zero-dependency, in-memory relay server for local testing.
|
Command relay-server is a zero-dependency, in-memory relay server for local testing. |
|
Package dns handles DNS configuration pushed by an OpenVPN server.
|
Package dns handles DNS configuration pushed by an OpenVPN server. |
|
internal
|
|
|
compress
Package compress implements the OpenVPN3 data-channel compression framing stubs for the 'compress lz4' and 'comp-lzo' options pushed by the server.
|
Package compress implements the OpenVPN3 data-channel compression framing stubs for the 'compress lz4' and 'comp-lzo' options pushed by the server. |
|
crypto
CBC cipher implementation for the OpenVPN3 data channel.
|
CBC cipher implementation for the OpenVPN3 data channel. |
|
ctls
Package ctls implements TLS-over-control-channel for OpenVPN3.
|
Package ctls implements TLS-over-control-channel for OpenVPN3. |
|
datachannel
Package datachannel implements the OpenVPN3 data channel: P_DATA_V2 packet framing, the encrypt/decrypt pipeline, and replay-protection sliding window.
|
Package datachannel implements the OpenVPN3 data channel: P_DATA_V2 packet framing, the encrypt/decrypt pipeline, and replay-protection sliding window. |
|
framing
Package framing implements the OpenVPN3 wire format: packet opcodes, the 2-byte length-prefixed TCP framing, and raw UDP framing.
|
Package framing implements the OpenVPN3 wire format: packet opcodes, the 2-byte length-prefixed TCP framing, and raw UDP framing. |
|
mssfix
Package mssfix clamps the TCP MSS option in SYN and SYN-ACK packets.
|
Package mssfix clamps the TCP MSS option in SYN and SYN-ACK packets. |
|
prf
Package prf implements the OpenVPN3 key-derivation pseudo-random function.
|
Package prf implements the OpenVPN3 key-derivation pseudo-random function. |
|
reliable
Package reliable implements the OpenVPN3 reliable control-channel transport: sequence numbers, ACK handling, retransmit queue, and a sliding receive window.
|
Package reliable implements the OpenVPN3 reliable control-channel transport: sequence numbers, ACK handling, retransmit queue, and a sliding receive window. |
|
mock
|
|
|
mockserver
command
Command mockserver is the go-openlawsvpn mock OpenVPN server.
|
Command mockserver is the go-openlawsvpn mock OpenVPN server. |
|
Package profile parses OpenVPN .ovpn configuration files.
|
Package profile parses OpenVPN .ovpn configuration files. |
|
Package relay implements the CLI agent side of the openlawsvpn SAML relay protocol.
|
Package relay implements the CLI agent side of the openlawsvpn SAML relay protocol. |
|
Netlink route management for the routing package.
|
Netlink route management for the routing package. |
|
Package testenv manages the mock openvpn3-core server for integration tests.
|
Package testenv manages the mock openvpn3-core server for integration tests. |
|
Package tun provides a TUN network interface for Linux.
|
Package tun provides a TUN network interface for Linux. |