Documentation
¶
Overview ¶
Package client реализует клиентскую половину туннеля: держит QUIC-соединение с сервером, проводит рукопожатие Noise и перекладывает пакеты между TUN и сетью.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GenerateKeyPair ¶ added in v0.2.0
GenerateKeyPair создаёт пару ключей клиента в виде строк base64.
Обёртка над noise.GenerateKey для тех, кому неудобно тянуть отдельный пакет ради одной операции, - например для мобильного фасада, где через границу проходят только простые типы.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client держит состояние подключения. Устройство создаётся один раз после первого удачного рукопожатия и переживает переподключения: так при обрыве не рушатся маршруты и сокеты приложений.
func NewWithOptions ¶
NewWithOptions создаёт клиента, которому устройство и настройку сети задаёт вызывающая сторона. Это точка встраивания ядра в приложение.
type Config ¶
type Config struct {
// Server - адрес сервера в виде host:port.
Server string `json:"server"`
// ServerKey - публичный ключ сервера. Именно он, а не TLS-сертификат,
// определяет, с кем мы согласны разговаривать.
ServerKey noise.PublicKey `json:"server_key"`
// PrivateKey - статический ключ клиента; его публичная часть должна
// быть в списке peers на сервере.
PrivateKey noise.PrivateKey `json:"private_key"`
// Name попадает в логи сервера, ни на что больше не влияет.
Name string `json:"name,omitempty"`
// TunName - имя интерфейса; пустое значение отдаёт выбор ядру.
TunName string `json:"tun_name,omitempty"`
// FullTunnel заворачивает в туннель весь IPv4-трафик, кроме пути до сервера.
FullTunnel bool `json:"full_tunnel,omitempty"`
// Routes - дополнительные подсети поверх тех, что предложил сервер.
Routes []netip.Prefix `json:"routes,omitempty"`
// SNI - имя, которое уедет в ClientHello открытым текстом.
// Пустое значение означает: взять хост из Server, если это не IP-адрес.
SNI string `json:"sni,omitempty"`
// DNS переопределяет резолверы, предложенные сервером.
DNS []netip.Addr `json:"dns,omitempty"`
// KeepIPv6 оставляет исходящий IPv6 включённым при полном туннеле.
//
// По умолчанию он запрещается: туннель возит только IPv4, и без запрета
// IPv6-трафик уходит мимо туннеля с настоящим адресом. Включайте, только
// если понимаете, что тем самым возвращаете утечку.
KeepIPv6 bool `json:"keep_ipv6,omitempty"`
// KeepSystemDNS запрещает трогать системные настройки DNS.
// По умолчанию клиент их меняет - иначе запросы уходят мимо туннеля
// и выдают провайдеру всё, что вы открываете.
KeepSystemDNS bool `json:"keep_system_dns,omitempty"`
}
Config - конфигурация клиента.
func LoadConfig ¶
LoadConfig читает конфигурацию клиента из JSON-файла.
func ParseConfig ¶ added in v0.2.0
ParseConfig разбирает конфигурацию из памяти.
Нужен встраиваемым приложениям: у них конфигурация приходит из хранилища платформы или по сети, а не из файла на диске.
func (Config) SNIOrDerived ¶
SNIOrDerived возвращает имя для ClientHello так же, как его выбирает клиент. Нужно внешним инструментам, подключающимся тем же способом.
type Options ¶
type Options struct {
// Device - готовое туннельное устройство. Пусто - ядро откроет само.
Device device.Device
// Network - настройка системной сети. Пусто - платформенная по умолчанию.
Network netconf.Configurator
// Logger - журнал. Пусто - журнал отключён.
Logger *slog.Logger
// OnState вызывается при каждой смене состояния туннеля. Нужен тем,
// кто показывает состояние в интерфейсе приложения.
OnState StateFunc
// ProtectSocket выводит сокет из-под туннеля до подключения.
//
// Обязателен на Android: там VpnService заворачивает в туннель весь
// трафик приложения, включая его собственный. Без защиты пакеты QUIC
// ушли бы в туннель, который они же и обслуживают, и подключение
// не состоялось бы никогда. На платформах, где такой проблемы нет,
// поле оставляют пустым.
ProtectSocket func(fd uintptr) error
}
Options - платформенная обвязка ядра.
Оба поля можно не задавать: на Linux ядро само откроет TUN и настроит сеть. Встраивая ядро в приложение на другой платформе, передайте готовое устройство и, если систему настраивает ОС, netconf.Noop.
type State ¶ added in v0.2.0
type State int
State - в каком состоянии находится туннель.
const ( // StateStopped - клиент не запущен либо остановлен. StateStopped State = iota // StateConnecting - идёт подключение или рукопожатие. StateConnecting // StateConnected - туннель поднят, трафик идёт. StateConnected // StateReconnecting - связь оборвалась, ждём следующей попытки. StateReconnecting )
type StateFunc ¶ added in v0.2.0
type StateFunc func(Status)
StateFunc вызывается при каждой смене состояния.
Вызов происходит из внутренних горутин ядра, поэтому обработчик должен возвращаться быстро: долгая работа в нём задержит переподключение.
type Status ¶ added in v0.2.0
type Status struct {
State State
// Address - виртуальный адрес, выданный сервером. Пуст, пока не подключены.
Address netip.Prefix
// Server - адрес сервера из конфигурации.
Server string
// Interface - имя интерфейса туннеля.
Interface string
// MTU, применённый к интерфейсу. Может отличаться от предложенного
// сервером, если путь не держит.
MTU int
// Since - когда состояние стало текущим.
Since time.Time
// RxBytes и TxBytes - объём расшифрованного и зашифрованного трафика
// с момента запуска, без учёта служебных данных.
RxBytes uint64
TxBytes uint64
// LastError - причина последнего обрыва. Пусто, если обрывов не было.
LastError string
}
Status - снимок состояния туннеля.
Нужен тем, кто встраивает ядро: показать пользователю, что происходит, без разбора журнала. Все поля заполнены по состоянию на момент вызова.