broker

package
v0.0.0-...-0a4c363 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2022 License: BSD-3-Clause Imports: 29 Imported by: 0

README

This is the Broker component of Snowflake.

Overview

The Broker handles the rendezvous by matching Snowflake Clients with Proxies, and passing their WebRTC Session Descriptions (the "signaling" step). This allows Clients and Proxies to establish a Peer connection.

It is analogous to Flashproxy's Facilitator, but bidirectional and domain-fronted.

The Broker expects:

  • Clients to send their SDP offer in a POST request, which will then block until the Broker responds with the answer of the matched Proxy.
  • Proxies to announce themselves with a POST request, to which the Broker responds with some Client's SDP offer. The Proxy should then send a second POST request soon after containing its SDP answer, which the Broker passes back to the same Client.

Running your own

The server uses TLS by default. There is a --disable-tls option for testing purposes, but you should use TLS in production.

The server automatically fetches certificates from Let's Encrypt as needed. Use the --acme-hostnames option to tell the server what hostnames it may request certificates for. You can optionally provide a contact email address, using the --acme-email option, so that Let's Encrypt can inform you of any problems.

In order to fetch certificates automatically, the server needs to open an additional HTTP listener on port 80. On Linux, you can use the setcap program, part of libcap2, to enable the broker to bind to low-numbered ports without having to run as root:

setcap 'cap_net_bind_service=+ep' /usr/local/bin/broker

You can control the listening broker port with the --addr option. Port 443 is the default.

You'll need to provide the URL of the custom broker to the client plugin using the --url $URL flag.

Documentation

Overview

Broker acts as the HTTP signaling channel. It matches clients and snowflake proxies by passing corresponding SessionDescriptions in order to negotiate a WebRTC connection.

This code is for loading database data that maps ip addresses to countries for collecting and presenting statistics on snowflake use that might alert us to censorship events.

The functions here are heavily based off of how tor maintains and searches their geoip database

The tables used for geoip data must be structured as follows:

Recognized line format for IPv4 is:

INTIPLOW,INTIPHIGH,CC
    where INTIPLOW and INTIPHIGH are IPv4 addresses encoded as big-endian 4-byte unsigned
    integers, and CC is a country code.

Note that the IPv4 line format

"INTIPLOW","INTIPHIGH","CC","CC3","COUNTRY NAME"

is not currently supported.

Recognized line format for IPv6 is:

IPV6LOW,IPV6HIGH,CC
    where IPV6LOW and IPV6HIGH are IPv6 addresses and CC is a country code.

It also recognizes, and skips over, blank lines and lines that start with '#' (comments).

Index

Constants

View Source
const (
	ClientTimeout = 30
	ProxyTimeout  = 30

	NATUnknown      = "unknown"
	NATRestricted   = "restricted"
	NATUnrestricted = "unrestricted"
)

Variables

This section is empty.

Functions

func GeoIPLoadFile

func GeoIPLoadFile(table GeoIPTable, pathname string) error

Loads provided geoip file into our tables Entries are stored in a table

func GetCountryByAddr

func GetCountryByAddr(table GeoIPTable, ip net.IP) (string, bool)

Returns the country location of an IPv4 or IPv6 address, and a boolean value that indicates whether the IP address was present in the geoip database

func RunBroker

func RunBroker(addr string)

Types

type BrokerContext

type BrokerContext struct {
	// contains filtered or unexported fields
}

func NewBrokerContext

func NewBrokerContext(metricsLogger *log.Logger) *BrokerContext

func (*BrokerContext) AddSnowflake

func (ctx *BrokerContext) AddSnowflake(id string, proxyType string, natType string) *Snowflake

Create and add a Snowflake to the heap. Required to keep track of proxies between providing them with an offer and awaiting their second POST with an answer.

func (*BrokerContext) Broker

func (ctx *BrokerContext) Broker()

goroutine which matches clients to proxies and sends SDP offers along. Safely processes proxy requests, responding to them with either an available client offer or nil on timeout / none are available.

func (*BrokerContext) RequestOffer

func (ctx *BrokerContext) RequestOffer(id string, proxyType string, natType string) *ClientOffer

Registers a Snowflake and waits for some Client to send an offer, as part of the polling logic of the proxy handler.

type ClientOffer

type ClientOffer struct {
	// contains filtered or unexported fields
}

Client offer contains an SDP and the NAT type of the client

type CountryStats

type CountryStats struct {
	// contains filtered or unexported fields
}

func (CountryStats) Display

func (s CountryStats) Display() string

type GeoIPEntry

type GeoIPEntry struct {
	// contains filtered or unexported fields
}

type GeoIPTable

type GeoIPTable interface {
	Len() int
	Append(GeoIPEntry)
	ElementAt(int) GeoIPEntry
	Lock()
	Unlock()
	// contains filtered or unexported methods
}

type GeoIPv4Table

type GeoIPv4Table struct {
	// contains filtered or unexported fields
}

func (*GeoIPv4Table) Append

func (table *GeoIPv4Table) Append(entry GeoIPEntry)

func (*GeoIPv4Table) ElementAt

func (table *GeoIPv4Table) ElementAt(i int) GeoIPEntry

func (*GeoIPv4Table) Len

func (table *GeoIPv4Table) Len() int

func (*GeoIPv4Table) Lock

func (table *GeoIPv4Table) Lock()

func (*GeoIPv4Table) Unlock

func (table *GeoIPv4Table) Unlock()

type GeoIPv6Table

type GeoIPv6Table struct {
	// contains filtered or unexported fields
}

func (*GeoIPv6Table) Append

func (table *GeoIPv6Table) Append(entry GeoIPEntry)

func (*GeoIPv6Table) ElementAt

func (table *GeoIPv6Table) ElementAt(i int) GeoIPEntry

func (*GeoIPv6Table) Len

func (table *GeoIPv6Table) Len() int

func (*GeoIPv6Table) Lock

func (table *GeoIPv6Table) Lock()

func (*GeoIPv6Table) Unlock

func (table *GeoIPv6Table) Unlock()

type Metrics

type Metrics struct {
	// contains filtered or unexported fields
}

Implements Observable

func NewMetrics

func NewMetrics(metricsLogger *log.Logger) (*Metrics, error)

func (*Metrics) LoadGeoipDatabases

func (m *Metrics) LoadGeoipDatabases(geoipDB string, geoip6DB string) error

func (*Metrics) UpdateCountryStats

func (m *Metrics) UpdateCountryStats(addr string, proxyType string, natType string)

type MetricsHandler

type MetricsHandler struct {
	// contains filtered or unexported fields
}

Implements the http.Handler interface

func (MetricsHandler) ServeHTTP

func (mh MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type PromMetrics

type PromMetrics struct {
	ProxyTotal       *prometheus.CounterVec
	ProxyPollTotal   *RoundedCounterVec
	ClientPollTotal  *RoundedCounterVec
	AvailableProxies *prometheus.GaugeVec
	// contains filtered or unexported fields
}

type ProxyPoll

type ProxyPoll struct {
	// contains filtered or unexported fields
}

Proxies may poll for client offers concurrently.

type RoundedCounter

type RoundedCounter interface {
	prometheus.Metric

	Inc()
}

New Prometheus counter type that produces rounded counts of metrics for privacy preserving reasons

type RoundedCounterVec

type RoundedCounterVec struct {
	*prometheus.MetricVec
}

New prometheus vector type that will track RoundedCounter metrics accross multiple labels

func NewRoundedCounterVec

func NewRoundedCounterVec(opts prometheus.CounterOpts, labelNames []string) *RoundedCounterVec

func (*RoundedCounterVec) With

Helper function to return the underlying RoundedCounter metric from MetricVec

type Snowflake

type Snowflake struct {
	// contains filtered or unexported fields
}

The Snowflake struct contains a single interaction over the offer and answer channels.

type SnowflakeHandler

type SnowflakeHandler struct {
	*BrokerContext
	// contains filtered or unexported fields
}

Implements the http.Handler interface

func (SnowflakeHandler) ServeHTTP

func (sh SnowflakeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type SnowflakeHeap

type SnowflakeHeap []*Snowflake

Implements heap.Interface, and holds Snowflakes.

func (SnowflakeHeap) Len

func (sh SnowflakeHeap) Len() int

func (SnowflakeHeap) Less

func (sh SnowflakeHeap) Less(i, j int) bool

func (*SnowflakeHeap) Pop

func (sh *SnowflakeHeap) Pop() interface{}

Only valid when Len() > 0.

func (*SnowflakeHeap) Push

func (sh *SnowflakeHeap) Push(s interface{})

func (SnowflakeHeap) Swap

func (sh SnowflakeHeap) Swap(i, j int)

Jump to

Keyboard shortcuts

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