Help us shape the future of Go! Take the 2026 Go Developer Survey

tlsrouter

package module
v0.11.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2026 License: MPL-2.0 Imports: 41 Imported by: 0

README

tlsrouter

A TLS Reverse Proxy for SNI and ALPN routing.

Supports both static and dynamic TLS routing.

tlsrouter \
   --config ~/.config/tlsrouter/backends.csv \
   --vault ~/.config/tlsrouter/secrets.tsv \
   --ip-domains vm.example.com \
   --networks 192.168.1.0/24 \
   --bind 0.0.0.0 \
   --port 443

Configured backends are loaded statically, while URLs like https://tls-192-168-1-100.vm.example.com are dynamically proxied - provided that the ip domain and ip-as-subdomain addresses match the allowed domain and networks.

If --ip-domains is set, the --config file is optional — tlsrouter can run in dynamic-only mode with no backends.csv. Each --ip-domains base domain is also resolved via DNS at startup (and on reload) and the resulting IPs are added to the set of allowed target IPs (.local suffix domains are skipped).

  • --config — Path to backends config CSV file (default: ~/.config/tlsrouter/backends.csv)
  • --vault — Path to vault TSV file (default: ~/.config/tlsrouter/secrets.tsv)
  • --ip-domains — Comma-separated base domains for dynamic IP URLs (default: example.localdomain)
  • --networks — Allowed networks for dynamic IP proxying (default: 169.254.0.0/16)
  • --bind — Address to bind to (default: 0.0.0.0)
  • --port — TLS port to listen on; -1 to disable (default: 443)
  • --plain-port — Plain HTTP port for redirects; -1 to disable (default: 80)
  • --ip-whitelist — TSV/CSV file or HTTP(S) URL of IPs, CIDRs, or domains that bypass IP blocking (default: ~/.config/tlsrouter/allowed.csv)
  • --ip-blacklist-extra — TSV/CSV file or HTTP(S) URL of extra IPs, CIDRs, or domains to block (default: empty)
  • --ip-blacklist-repo — git repo URL for the base IP blacklist, or none to disable (default: https://github.com/bitwire-it/ipblocklist.git)
  • --ip-blacklist-dir — local directory for the base git blacklist checkout (default: ~/.local/share/bitwire-it/ipblocklist)
  • --verbose — Enable debug trace output (default: false)
  • --version — Print version and exit

IP policy sources use the first column of each TSV/CSV row. For example:

# host\tcomment
127.0.0.1\t# ip
example.com\t# domain
https://infra.example.com/list.tsv\t# nested source

Blank lines and lines starting with # are ignored; later columns are ignored metadata. An optional header row with network or source as the first column is recognized and skipped (case-insensitive). Nested HTTP(S) sources use the same format and are supported up to two levels. URL userinfo supplies Basic Auth. Whitelist entries take precedence over blacklist entries.

If a whitelist cannot be read, fetched, parsed, or loaded from its cache, all blacklists are disabled. This fail-open behavior avoids catastrophic lockout during transient errors in this critical service. URL-list cache data is stored under $XDG_CACHE_HOME/tlsrouter/iplist/ or ~/.cache/tlsrouter/iplist/. The git blacklist checkout uses the separate --ip-blacklist-dir directory.

Environment Variables

All runtime flags can be set via environment variables (flags take precedence). --version is not env-settable (it is not a runtime option).

Flag Env Var Default
--port PORT 443 (-1 to disable)
--plain-port PLAIN_PORT 80 (-1 to disable)
--bind BIND 0.0.0.0
--config CONFIG_FILE ~/.config/tlsrouter/backends.csv
--vault VAULT_FILE ~/.config/tlsrouter/secrets.tsv
--ip-domains DYNAMIC_IP_DOMAIN example.localdomain
--networks DYNAMIC_HOST_NETWORKS 169.254.0.0/16
--verbose VERBOSE false
--ip-whitelist WHITELIST ~/.config/tlsrouter/allowed.csv
--ip-blacklist-extra BLACKLIST_EXTRA (empty)
--ip-blacklist-repo BLACKLIST_REPO https://github.com/bitwire-it/ipblocklist.git
--ip-blacklist-dir BLACKLIST_DIR ~/.local/share/bitwire-it/ipblocklist

A .env file in the working directory is loaded automatically.

DNS Authorization

Sites are configured through DNS.

CNAME (for subdomains)

Both http/1.1 and ssh (terminated) can be enabled by setting a CNAME to the direct IP domain:

# terminates https to 3080
CNAME   site-a.whatever.com  tls-192-168-1-100.vm.example.net   300

# proxies non-terminated to 443
CNAME   site-a.whatever.com  tcp-192-168-1-100.vm.example.net   300

If you'd like to use a CNAME for convenience for multiple records, use cname.<ip-domain>, such as cname.vm.example.net.

CNAME   sites.whatever.com               cname.vm.example.net   300

Note: all ports in the table below are public and you should bind to localhost or use a firewall if you wish to run things on those ports privately.

A + SRV (for apex domains)
A                  whatever.com                              123.1.2.3  300
SRV     _http._tcp.whatever.com     10 3080 tls-10-11-1-123.a.bnna.net  300 10
SRV      _ssh._tcp.whatever.com     10   22 tls-10-11-1-123.a.bnna.net  300 10

Note: ports must be selected according to the table below. Arbitrary ports are not allowed for security reasons (anyone can set records on their domain to your IP address).

SRV (to enable more protocols)

Whether using CNAME or A records, SRV records will enable additional proxying.

SRV             _h2._tcp.whatever.com   10  443 tcp-10-11-1-123.a.bnna.net  300 10
SRV     _postgresql._tcp.whatever.com   10 3080 tls-10-11-1-123.a.bnna.net  300 10

ALPN names can be translated to service names in one of two ways:

  1. replace all . (periods) with -, and replace / with _
  2. drop anything after / and replace all . (periods) with -

For example: http and http_1-1 are both valid for http/1.1

Note: ports must be selected according to the table below. Arbitrary ports are not allowed for security reasons (anyone can set records on their domain to your IP address).

Dynamic IP URL Mapping

There are two URL patterns:

  • <layer4>-<ipv4-octets>-<ip-domain> — template
  • tls-192-168-1-100.example.com — Handles / Terminates TLS
  • tcp-192-168-1-100.example.com — Raw TCP Passthrough / Non-Terminating

ALL TRAFFIC uses port 443 externally.

If the Raw TCP URL is used, then the Raw Port will be used - proxied traffic will remain encrypted.

If the Terminating URL is used, then the Decrypted Port will be used.

Why non-standard ports? So that unencrypted services, which may have been intended for private networking, aren't exposed to the Internet by default.

Port notation: The Decrypted Port is 10000 + <normal plain port> in most cases. The *N* markers show the prefix from 10000 concatenated with the plain port.

ALPN Raw Port Decrypted Port Comment
http/1.1 443 3080 3080 to be familiar, but non-default like 3000, 8080, and 80
ssh 44322 22 sshd can't handle sclient tls directly, hence 44322 for tls
--- --- --- special protocols
acme-tls/1 443 - for ACME / Let's Encrypt TLS SNI ALPN challenges
h2 443 - proper HTTP/2 requires raw passthrough and has no plain port
h2c - 3080 plain HTTP/2, for testing/debugging
--- --- --- 10,000 is added to the default ports below
coap 5684 15683 IoT, plain port is 5683
dicom 2762 10104 biomedical imaging, plain port is 104
dot 853 10053 dns-over-tls, normal plain port is 53 (udp and tcp)
ftp 990 10021 normal plain port is 21, but it's more complicated than that
imap 993 10143 normal plain port is 143
irc 6697 16667 normal plain port is 6667
managesieve 4190 14190 for mail filtering, plain is also 4190
mqtt 8883 11883 normal plain port is 1883
mysql 3306 13306 MySQL, direct TLS
nntp 563 10119 for News Servers, plain port is 119
ntske/1 4460 10123 for NTP, normal plain port is 123
pop3 995 10110 normal plain port is 110
postgresql 5432 15432 Postgres 17+ supports direct TLS
tds/8.0 1433 11433 MS SQL 2025+ supports direct TLS
radius/1.0 2083 12083 legacy TLS optional
radius/1.1 2083 12083 direct TLS required
sip 5061 15060 normal plain port is 5060 (or 5080)
smb 10445 10445 Either use requires tunneling (native SMB TLS requires QUIC)
webrtc 443 10080 10080 to be familiar, but not 18080, 8080, 8081, or 9000
c-webrtc 443 10080 "
xmpp-client 5223 15222 client-to-server communication, default 5222 (plain)
xmpp-server 5270 15269 server-to-server communication, default 5269 (plain)

For all registered ALPNs, see https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml.

Excluded:

  • co is UDP-only
  • doq DNS over QUIC is UDP-only
  • http/0.9, http/1.0 superseded by http/1.1
  • h3 HTTP over QUIC is UDP-only
  • nnsp has no port designation (and isn't actually referenced in the RFC)
  • spdy/* superseded by h2
  • stun.turn has more complex implications that I'm ready to consider
  • stun.nat-discovery (same)
  • sunrpc probably not relevant

Static Config (backends.csv)

The config file is a CSV with the following header row (order does not matter; columns are matched by name):

app_slug,domain,alpn,backend_address,backend_port,terminate_tls,connect_tls,rewrite_host,skip_tls_verify,auth,allowed_client_hostnames

Example:

_admin,vms.example.com,admin,vault://5d7d83f3...,,,,,,,
myapp,site.example.com,ssh,127.0.0.1,22,false,false,false,,,
myapp,site.example.com,http/1.1,172.16.0.1,443,true,true,true,,vault://a1b2c3...,
Field Description
app_slug Application group; _admin with alpn=admin enables the admin API
domain SNI domain to match (wildcards via *.example.com)
alpn ALPN to match (e.g. http/1.1, ssh, h2); omitted defaults to http/1.1
backend_address Backend host or IP
backend_port Backend port
terminate_tls true → tlsrouter terminates TLS and decrypts traffic
connect_tls true → re-encrypts to backend (upstream TLS)
rewrite_host Host header value to set when proxying HTTP
skip_tls_verify true → skip backend TLS certificate verification
auth Vault entry reference (vault://<id>); fails closed if missing
allowed_client_hostnames Comma-separated client hostnames allowed to connect

Multiple rows per domain enable different ALPNs (e.g. ssh and http/1.1).

Vault & Password Hashing

The --vault file (secrets.tsv) stores auth secrets referenced by vault://<id> in the config. Use the tabvault CLI to manage it:

# Create the vault file first
touch ~/.config/tlsrouter/secrets.tsv

# Generate a new random secret and store it
tabvault ~/.config/tlsrouter/secrets.tsv add

# Append a token to an existing vault entry
tabvault ~/.config/tlsrouter/secrets.tsv append <vault-id>

# Verify a password against a vault entry
tabvault ~/.config/tlsrouter/secrets.tsv verify <vault-id>

For HTTP Basic Auth backends, generate a PBKDF2 password hash with the hash-password subcommand:

# Interactive (prompts twice for confirmation)
tlsrouter hash-password

# Non-interactive (from stdin)
echo -n 'my-password' | tlsrouter hash-password

This outputs a $pbkdf2-sha256$10000$<salt>$<key> hash suitable for the vault.

HTTP API

tlsrouter exposes HTTP endpoints on the admin domain(s) configured via _admin in backends.csv:

Public endpoints
Method & Path Description
GET /version Version info (also at /api/version, /api/public/version)
GET /status Uptime and config hash (also at /api/status, /api/public/status)
Admin API
Method & Path Description
GET /api/config/current Current running config
GET /api/config/new Pending/staged config
PUT /api/config/new/{HashOrRev} Activate a staged config
GET /api/services List configured services
POST /api/services Create or update a service
GET /api/connections List active connections
DELETE /api/remotes/{RemoteAddr} Close connections from a remote
DELETE /api/clients/{Service} Close connections to a service

Signals

Signal Behavior
SIGUSR1 Reload backends.csv and the vault without restart; starts a new listener with a fresh DNS cache and gracefully shuts down the old
SIGINT Graceful shutdown (5s grace period), then exit
SIGTERM Graceful shutdown (5s grace period), then exit

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrDoNotTerminate = fmt.Errorf("a self-terminating match was found")
View Source
var HTTPFamilyALPNs = []string{
	"h3",
	"h2",
	"h2c",
	"http/0.9",
	"http/1.0",
	"http/1.1",
}
View Source
var Verbose bool

Functions

func EscapeAndRenderURL

func EscapeAndRenderURL(r *http.Request) (properURL, htmlURL, attrURL, redirectBody string)

EscapeAndRenderURL uses both querystring and html escape for the appropriate style - hrefURL is the safest

func HandleHTTPSRedirect

func HandleHTTPSRedirect(w http.ResponseWriter, r *http.Request)

HandleHTTPSRedirect issues a client-side redirect via HTML meta refresh. - If the client accepts text/html (browser-like), includes <link rel="canonical">. - All clients receive 200 OK with HTML body containing meta refresh and link. - Uses the same status, headers, and logic regardless of Accept. - If Host header is missing, returns 400 Bad Request.

func LintConfig

func LintConfig(conf *Config, allowedAlpns []string) error

func ListenAndRedirectPlainHTTP

func ListenAndRedirectPlainHTTP(addr string) error

ListenAndRedirectPlainHTTP starts an HTTP listener on :80 that redirects to HTTPS

func NormalizeConfig

func NormalizeConfig(conf *Config) (map[string][]string, map[SNIALPN]*dnsCacheEntry)

func RecordsToCSV

func RecordsToCSV(csvw *csv.Writer, records []CSVRecord) error

RecordsToCSV serializes a list of CSV records to a CSV string.

func TunnelTCPConn

func TunnelTCPConn(snialpn SNIALPN, cConn net.Conn, beConn net.Conn) (r int64, w int64, retErr error)

TunnelTCPConn is a bi-directional copy, calling io.Copy for both connections

Types

type ACMEDNS

type ACMEDNS struct {
	Domains       []string              `json:"domains"`
	DNSProvider   certmagic.DNSProvider `json:"-"`
	DNS01Provider struct {
		API    string `json:"api"`
		Config struct {
			APIToken string `json:"api_token"`
		} `json:"config"`
	} `json:"dns01_provider"`
}

type APIService

type APIService struct {
	AppSlug      string   `json:"app_slug"`
	Slug         string   `json:"slug"`
	Comment      *string  `json:"comment,omitempty"`
	Disabled     *bool    `json:"disabled,omitempty"`
	Domains      []string `json:"domains"`
	ALPNs        []string `json:"alpns"`
	BackendSlugs []string `json:"backend_slugs,omitempty"`
}

APIService defines a rule for matching domains and ALPNs to backends.

type Backend

type Backend struct {
	Slug          string             `json:"slug"`
	Comment       string             `json:"comment,omitempty"`
	Disabled      bool               `json:"disabled,omitempty"`
	ALPNs         []string           `json:"alpns,omitempty"`
	Address       string             `json:"address"`
	Port          uint16             `json:"port"`
	Host          string             `json:"-"`
	HTTPTunnel    tun.InjectListener `json:"-"`
	PROXYProto    int                `json:"proxy_protocol,omitempty"`
	TerminateTLS  bool               `json:"terminate_tls"`
	ForceHTTP     bool               `json:"force_http,omitempty"`
	ConnectTLS    bool               `json:"connect_tls"`
	RewriteHost   string             `json:"rewrite_host,omitempty"`
	SkipTLSVerify bool               `json:"connect_insecure"`
	AuthToken     string             `json:"auth_token,omitempty"`
}

Backend defines a proxy destination.

type BasicVerifier added in v0.8.0

type BasicVerifier interface {
	Verify(string, string) error
}

type CSVRecord

type CSVRecord struct {
	AppSlug                string
	Domain                 string
	ALPN                   string
	BackendAddress         string
	BackendPort            uint16
	TerminateTLS           bool
	ConnectTLS             bool
	RewriteHost            string
	SkipTLSVerify          bool
	Auth                   string
	AllowedClientHostnames string
}

CSVRecord represents a single row in the CSV output.

type CacheState added in v0.8.0

type CacheState int
const (
	CacheFresh CacheState = iota
	CacheStale
	CacheExpired
)

type Config

type Config struct {
	Revision              string         `json:"rev,omitempty"`
	Hash                  string         `json:"hash,omitempty"`
	Handler               *http.ServeMux `json:"-"`
	ACMEDirectoryEndpoint string         `json:"-"`
	FilePath              string         `json:"-"`
	FileTime              time.Time      `json:"-"` // from file date

	TabVault *tabvault.TabVault `json:"-"`
	AdminDNS ConfigAdmin        `json:"admin"`
	Apps     []ConfigApp        `json:"apps"`

	Networks  []net.IPNet `json:"dynamic_host_networks"`
	IPDomains []string    `json:"dynamic_ip_domains"`
	IPs       []net.IP    `json:"-"`
	// contains filtered or unexported fields
}

Config holds the TLS routing configuration and hostname resolutions. Note: JSON keys are encoded in a consistent order, as per struct-order, and generic map keys are sorted.

func ReadCSVToConfig

func ReadCSVToConfig(r *csv.Reader) (*Config, error)

func (*Config) IsAllowedIP added in v0.9.0

func (c *Config) IsAllowedIP(ip net.IP) bool

func (*Config) Reincarnate

func (c *Config) Reincarnate()

func (*Config) Save

func (c *Config) Save() error

Save must not be called after the atomic Store()

func (*Config) SetSigChan

func (c *Config) SetSigChan(sigChan chan os.Signal)

func (*Config) ShortSHA2

func (c *Config) ShortSHA2() string

ShortSHA2 is not safe for use after atomic Store()

func (*Config) ToCSV

func (c *Config) ToCSV(w io.Writer) error

ToCSV converts the config to a CSV string, using ToRecords and RecordsToCSV.

func (*Config) ToRecords

func (c *Config) ToRecords() ([]CSVRecord, error)

ToRecords creates a sorted list of CSV records from the config.

type ConfigAdmin

type ConfigAdmin struct {
	ConfigDNS
	AdminUser  string `json:"admin_username"`
	AdminToken string `json:"admin_token"`
}

type ConfigApp

type ConfigApp struct {
	Label        string          `json:"label"`
	Slug         string          `json:"slug"`
	Comment      string          `json:"comment,omitempty"`
	Disabled     bool            `json:"disabled,omitempty"`
	DNSProviders []ConfigDNS     `json:"dns_providers,omitempty"`
	Services     []ConfigService `json:"services"`
}

ConfigApp describes an arbitrarily relationship between services

type ConfigConflict

type ConfigConflict struct {
	Hash     string `json:"hash"`
	Revision string `json:"rev"`
}

type ConfigDNS

type ConfigDNS struct {
	Slug     string   `json:"slug"`
	Comment  string   `json:"comment,omitempty"`
	Disabled bool     `json:"disabled,omitempty"`
	Domains  []string `json:"domains,omitempty"`
	XDomains []string `json:"excluded_domains,omitempty"`
	API      string   `json:"api"`
	APIToken string   `json:"api_token"`
}

ConfigDNS defines libdns-style DNS API options

type ConfigError

type ConfigError struct {
	Error string `json:"error"`
}

type ConfigService

type ConfigService struct {
	Slug                   string         `json:"slug"`
	Comment                string         `json:"comment,omitempty"`
	Disabled               bool           `json:"disabled,omitempty"`
	Domains                []string       `json:"domains"`
	ALPNs                  []string       `json:"alpns,omitempty"`
	Backends               []Backend      `json:"backends"`
	CurrentBackend         *atomic.Uint32 `json:"-"`
	AllowedClientHostnames []string       `json:"allowed_client_hostnames,omitempty"`
}

ConfigService defines a rule for matching domains and ALPNs to backends.

func (*ConfigService) GenSlug

func (srv *ConfigService) GenSlug() string

type ErrorNoTLSConfig

type ErrorNoTLSConfig string

func (ErrorNoTLSConfig) Error

func (e ErrorNoTLSConfig) Error() string

type Int52

type Int52 int64

Int52 is a newtype for int that marshals/unmarshals as int64 in JSON.

func (Int52) MarshalJSON

func (i Int52) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*Int52) UnmarshalJSON

func (i *Int52) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type Int52Time

type Int52Time int64

Int52Time is a newtype for int64 that marshals/unmarshals a UnixMilli() as ISO Time in JSON.

func (Int52Time) MarshalJSON

func (i Int52Time) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*Int52Time) UnmarshalJSON

func (i *Int52Time) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type JSONError

type JSONError struct {
	Error  string `json:"error"`
	Code   string `json:"code"`
	Detail string `json:"detail"`
}

JSONError represents an API error response

type JSONTime

type JSONTime time.Time

JSONTime is a newtype for int64 that marshals/unmarshals a UnixMilli() as ISO Time in JSON.

func (JSONTime) MarshalJSON

func (t JSONTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*JSONTime) UnmarshalJSON

func (t *JSONTime) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type ListenConfig

type ListenConfig struct {
	Conns         sync.Map
	TLSMismatches sync.Map

	Context               context.Context
	ACMEDirectoryEndpoint string

	Close func()

	IPPolicy *ippolicy.Policy
	// contains filtered or unexported fields
}

func NewListenConfig

func NewListenConfig(conf Config) *ListenConfig

func (*ListenConfig) ListenAndProxy

func (lc *ListenConfig) ListenAndProxy(addr string, mux *http.ServeMux) error

func (*ListenConfig) LoadConfig

func (lc *ListenConfig) LoadConfig() Config

func (*ListenConfig) RouteCloseClients

func (lc *ListenConfig) RouteCloseClients(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteCloseRemotes

func (lc *ListenConfig) RouteCloseRemotes(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteGetConfig

func (lc *ListenConfig) RouteGetConfig(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteGetNewConfig

func (lc *ListenConfig) RouteGetNewConfig(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteListConnections

func (lc *ListenConfig) RouteListConnections(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteListServices

func (lc *ListenConfig) RouteListServices(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteSetNewConfig

func (lc *ListenConfig) RouteSetNewConfig(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) RouteSetService

func (lc *ListenConfig) RouteSetService(w http.ResponseWriter, r *http.Request)

func (*ListenConfig) Shutdown

func (lc *ListenConfig) Shutdown(ctx context.Context)

TODO move to *Listener

func (*ListenConfig) StoreConfig

func (lc *ListenConfig) StoreConfig(conf Config)

type PConn

type PConn struct {
	Self         bool      `json:"self,omitempty"`
	Address      string    `json:"address"`
	ServerName   string    `json:"servername"`
	ALPN         string    `json:"alpn"`
	Read         Int52     `json:"read"`
	Written      Int52     `json:"written"`
	Since        JSONTime  `json:"since"`
	PlainRead    Int52     `json:"plain_read"`
	PlainWritten Int52     `json:"plain_written"`
	LastRead     Int52Time `json:"last_read"`
	LastWrite    Int52Time `json:"last_write"`
}

func WConnToPConn

func WConnToPConn(wconn *wrappedConn) PConn

type PlainConn

type PlainConn struct {
	BytesRead    atomic.Uint64
	BytesWritten atomic.Uint64
	// contains filtered or unexported fields
}

PlainConn wraps a *tls.Conn as a private field (not embedded) for two reasons:

  1. Byte counting — Read/Write intercept plaintext traffic so we can track bandwidth at both the TLS and TCP layers independently.
  2. h2 detection — exposing only net.Conn makes http.Server's rwc.(*tls.Conn) assertion fail, so h2c-preface detection runs on the decrypted stream.

ConnectionState is still accessible via an explicit method for stats/reporting.

func NewPlainConn

func NewPlainConn(tc *tls.Conn) *PlainConn

func (*PlainConn) Close added in v0.8.0

func (p *PlainConn) Close() error

func (*PlainConn) LocalAddr added in v0.8.0

func (p *PlainConn) LocalAddr() net.Addr

func (*PlainConn) Read

func (p *PlainConn) Read(b []byte) (int, error)

func (*PlainConn) RemoteAddr added in v0.8.0

func (p *PlainConn) RemoteAddr() net.Addr

func (*PlainConn) SetDeadline added in v0.8.0

func (p *PlainConn) SetDeadline(t time.Time) error

func (*PlainConn) SetReadDeadline added in v0.8.0

func (p *PlainConn) SetReadDeadline(t time.Time) error

func (*PlainConn) SetWriteDeadline added in v0.8.0

func (p *PlainConn) SetWriteDeadline(t time.Time) error

func (*PlainConn) TLSConnectionState added in v0.8.0

func (p *PlainConn) TLSConnectionState() tls.ConnectionState

TLSConnectionState exposes TLS state for reporting. Named to avoid matching net/http's unexported connectionStater interface, which would set tlsState and prevent h2c preface detection on the decrypted stream.

func (*PlainConn) Write

func (p *PlainConn) Write(b []byte) (int, error)

type SNIALPN

type SNIALPN string

func NewSNIALPN

func NewSNIALPN(sni, alpn string) SNIALPN

func (SNIALPN) ALPN

func (s SNIALPN) ALPN() string

ALPN returns the ALPN part of the SNIALPN (after ">")

func (SNIALPN) SNI

func (s SNIALPN) SNI() string

SNI returns the SNI part of the SNIALPN (before ">")

Directories

Path Synopsis
bin
cmd
tabvault command
tlsrouter command
Package dnsresolver provides a parallel DNS resolver with automatic fallback servers.
Package dnsresolver provides a parallel DNS resolver with automatic fallback servers.
internal
net
tun
tools
alpn-get command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL