Documentation
¶
Overview ¶
Package netem is a framework to write integration tests that use TCP/IP stacks implemented in userspace.
Assuming that your code depends on UnderlyingNetwork (or on its wrapper Net), you can write your tests to create and use Gvisor-based TCP/IP stacks in userspace. To this end, use the NewUNetStack constructor or create it in the context of a specific network topology (explained below). Because UNetStack implements the UnderlyingNetwork model, your code can now use the TCP/IP stack in userspace as opposed to the Go standard library.
For normal operations, instead, you can use the [Stdlib] struct. This struct implements UnderlyingNetwork using the Go standard library. So, when your code uses a [Stdlib] as its UnderlyingNetwork, it will use your host network as usual.
A UNetStack alone is not attached to any link and so it cannot communicate with any other host. To connect two UNetStack, use NewLink. This factory will create a Link, which implements the following:
- delivery of TCP/IP packets between the two UNetStack;
- optionally, emulation of packet loss rate, addition of extra round trip time, and presence of DPI rules.
You configure the link properties using LinkConfig, which is the structure you pass to NewLink.
Rather than using a Link to connect two UNetStack in point-to-point fashion, you can alternatively create a Router. A new Router is not attached to any other host and so is not routing. To attach a UNetStack to a router, create a RouterPort and a Link between such a UNetStack and the RouterPort. Using the Router you can create complex topologies.
Because creating topologies manually is error prone, we have two predefined topologies:
- the PPPTopology automates creating a Link between two UNetStack instances;
- the StarTopology automates creating a Router and links between UNetStack and RouterPort.
The UnderlyingNetwork model includes a method to obtain the root X.509 certificate pool to use. When you are using a UNetStack, the root X.509 is constructed such that we are able to automatically produce a certificate for any SNI on the server side as long as the client code uses such a root.
Example (DpiCloseConnectionForString) ¶
This example shows how to use DPI to provoke an EOF when you see an offending string.
package main import ( "fmt" "log" "net" "net/http" "time" "github.com/ooni/netem" ) func main() { // Create a star topology for our hosts. topology := netem.MustNewStarTopology(&netem.NullLogger{}) defer topology.Close() // Create DPI engine in the client link dpi := netem.NewDPIEngine(&netem.NullLogger{}) // Add client stack to topology. Note that we don't need to // close the clientStack: the topology will do that. // // Note that we need to add delay because several DPI rules // rely on race conditions and delay helps. clientStack, err := topology.AddHost( "10.0.0.1", // host IP address "8.8.8.8", // host DNS resolver IP address &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, DPIEngine: dpi, }, ) if err != nil { log.Fatal(err) } // Add DNS server stack to topology. dnsServerStack, err := topology.AddHost( "8.8.8.8", "8.8.8.8", // this host is its own DNS resolver &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // Add HTTPS server stack to topology. httpsServerStack, err := topology.AddHost( "5.4.3.21", "8.8.8.8", &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // spawn a DNS server with the required configuration. dnsConfig := netem.NewDNSConfig() dnsConfig.AddRecord("www.example.com", "", "5.4.3.21") dnsConfig.AddRecord("example.com", "", "5.4.3.21") dnsServer, err := netem.NewDNSServer( &netem.NullLogger{}, dnsServerStack, "8.8.8.8", dnsConfig, ) if err != nil { log.Fatal(err) } defer dnsServer.Close() // spawn an HTTP server with the required configuration mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Bonsoir, Elliot!")) }) httpsAddr := &net.TCPAddr{ IP: net.ParseIP("5.4.3.21"), Port: 80, } httpsListener, err := httpsServerStack.ListenTCP("tcp", httpsAddr) if err != nil { log.Fatal(err) } httpsServer := &http.Server{ Handler: mux, } go httpsServer.Serve(httpsListener) defer httpsServer.Close() // create an HTTP transport using the clientStack txp := netem.NewHTTPTransport(clientStack) // add DPI rule that closes the connection for the www.example.com string dpi.AddRule(&netem.DPICloseConnectionForString{ Logger: &netem.NullLogger{}, ServerIPAddress: "5.4.3.21", ServerPort: 80, String: "www.example.com", }) // Note that all the code that follows is standard Go code that // would work for any implementation of http.RoundTripper. { // create HTTP request req, err := http.NewRequest("GET", "http://www.example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) fmt.Printf("%s %v\n", err.Error(), resp == nil) } { // create HTTP request req, err := http.NewRequest("GET", "http://example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) fmt.Printf("%v %v\n", err != nil, resp == nil) defer resp.Body.Close() } }
Output: EOF true false false
Example (DpiDoesNotAffectLoopbackTraffic) ¶
This is a scenario where a www server modeling www.example.com communicates with itself, therefore, the DPI does not have any effect.
package main import ( "context" "fmt" "io" "log" "net" "net/http" "time" apexlog "github.com/apex/log" "github.com/ooni/netem" ) func main() { // Create a star topology for our hosts. topology := netem.MustNewStarTopology(&netem.NullLogger{}) defer topology.Close() // Create DPI engine in the wwwStack link dpi := netem.NewDPIEngine(&netem.NullLogger{}) // IP addresses used by this scenario const ( wwwAddress = "93.184.216.34" resolverAddress = "8.8.8.8" ) // Add the WWW stack to topology. Note that we don't need to // close the stack: the topology will do that. // // Note that we need to add delay because several DPI rules // rely on race conditions and delay helps. wwwStack, err := topology.AddHost( wwwAddress, // host IP address resolverAddress, // host DNS resolver IP address &netem.LinkConfig{ DPIEngine: dpi, LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // Add DNS server stack to topology. dnsServerStack, err := topology.AddHost( resolverAddress, resolverAddress, // this host is its own DNS resolver &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // spawn a DNS server with the required configuration. dnsConfig := netem.NewDNSConfig() dnsConfig.AddRecord("www.example.com", "", wwwAddress) dnsServer, err := netem.NewDNSServer( &netem.NullLogger{}, dnsServerStack, resolverAddress, dnsConfig, ) if err != nil { log.Fatal(err) } defer dnsServer.Close() // spawn an HTTP server with the required configuration mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Bonsoir, Elliot!")) }) httpsAddr := &net.TCPAddr{ IP: net.ParseIP(wwwAddress), Port: 80, } httpsListener, err := wwwStack.ListenTCP("tcp", httpsAddr) if err != nil { log.Fatal(err) } httpsServer := &http.Server{ Handler: mux, } go httpsServer.Serve(httpsListener) defer httpsServer.Close() // create an HTTP transport using the wwwStack // // This is crucial: it means the traffic is not going to exit the // loopback interface of stack, so DPI wouldn't see it txp := netem.NewHTTPTransport(wwwStack) blockpage := []byte(`<html><head><title>451 Unavailable For Legal Reasons</title></head><body><center><h1>451 Unavailable For Legal Reasons</h1></center><p>This content is not available in your jurisdiction.</p></body></html>`) // add DPI rule that drops traffic for the www.example.com string dpi.AddRule(&netem.DPISpoofBlockpageForString{ HTTPResponse: netem.DPIFormatHTTPResponse(blockpage), Logger: apexlog.Log, ServerIPAddress: wwwAddress, ServerPort: 80, String: "www.example.com", }) // Note that all the code that follows is standard Go code that // would work for any implementation of http.RoundTripper. { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // create HTTP request req, err := http.NewRequestWithContext(ctx, "GET", "http://www.example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", string(respBody)) } }
Output: Bonsoir, Elliot!
Example (DpiDropTrafficForString) ¶
This example shows how to use DPI to drop traffic after you see a given string,
package main import ( "context" "fmt" "log" "net" "net/http" "time" "github.com/ooni/netem" ) func main() { // Create a star topology for our hosts. topology := netem.MustNewStarTopology(&netem.NullLogger{}) defer topology.Close() // Create DPI engine in the client link dpi := netem.NewDPIEngine(&netem.NullLogger{}) // Add client stack to topology. Note that we don't need to // close the clientStack: the topology will do that. // // Note that we need to add delay because several DPI rules // rely on race conditions and delay helps. clientStack, err := topology.AddHost( "10.0.0.1", // host IP address "8.8.8.8", // host DNS resolver IP address &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, DPIEngine: dpi, }, ) if err != nil { log.Fatal(err) } // Add DNS server stack to topology. dnsServerStack, err := topology.AddHost( "8.8.8.8", "8.8.8.8", // this host is its own DNS resolver &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // Add HTTPS server stack to topology. httpsServerStack, err := topology.AddHost( "5.4.3.21", "8.8.8.8", &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // spawn a DNS server with the required configuration. dnsConfig := netem.NewDNSConfig() dnsConfig.AddRecord("www.example.com", "", "5.4.3.21") dnsConfig.AddRecord("example.com", "", "5.4.3.21") dnsServer, err := netem.NewDNSServer( &netem.NullLogger{}, dnsServerStack, "8.8.8.8", dnsConfig, ) if err != nil { log.Fatal(err) } defer dnsServer.Close() // spawn an HTTP server with the required configuration mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Bonsoir, Elliot!")) }) httpsAddr := &net.TCPAddr{ IP: net.ParseIP("5.4.3.21"), Port: 80, } httpsListener, err := httpsServerStack.ListenTCP("tcp", httpsAddr) if err != nil { log.Fatal(err) } httpsServer := &http.Server{ Handler: mux, } go httpsServer.Serve(httpsListener) defer httpsServer.Close() // create an HTTP transport using the clientStack txp := netem.NewHTTPTransport(clientStack) // add DPI rule that drops traffic for the www.example.com string dpi.AddRule(&netem.DPIDropTrafficForString{ Logger: &netem.NullLogger{}, ServerIPAddress: "5.4.3.21", ServerPort: 80, String: "www.example.com", }) // Note that all the code that follows is standard Go code that // would work for any implementation of http.RoundTripper. { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // create HTTP request req, err := http.NewRequestWithContext(ctx, "GET", "http://www.example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) fmt.Printf("%s - %v\n", err.Error(), resp == nil) } { // create HTTP request req, err := http.NewRequest("GET", "http://example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) fmt.Printf("%v - %v\n", err != nil, resp == nil) defer resp.Body.Close() } }
Output: context deadline exceeded - true false - false
Example (DpiSpoofBlockpageForString) ¶
This example shows how to use DPI to spoof a blockpage for a string
package main import ( "context" "fmt" "io" "log" "net" "net/http" "time" apexlog "github.com/apex/log" "github.com/ooni/netem" ) func main() { // Create a star topology for our hosts. topology := netem.MustNewStarTopology(&netem.NullLogger{}) defer topology.Close() // Create DPI engine in the client link dpi := netem.NewDPIEngine(&netem.NullLogger{}) // Add client stack to topology. Note that we don't need to // close the clientStack: the topology will do that. // // Note that we need to add delay because several DPI rules // rely on race conditions and delay helps. clientStack, err := topology.AddHost( "10.0.0.1", // host IP address "8.8.8.8", // host DNS resolver IP address &netem.LinkConfig{ DPIEngine: dpi, LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // Add DNS server stack to topology. dnsServerStack, err := topology.AddHost( "8.8.8.8", "8.8.8.8", // this host is its own DNS resolver &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // Add HTTPS server stack to topology. httpsServerStack, err := topology.AddHost( "5.4.3.21", "8.8.8.8", &netem.LinkConfig{ LeftToRightDelay: time.Millisecond, RightToLeftDelay: time.Millisecond, }, ) if err != nil { log.Fatal(err) } // spawn a DNS server with the required configuration. dnsConfig := netem.NewDNSConfig() dnsConfig.AddRecord("www.example.com", "", "5.4.3.21") dnsConfig.AddRecord("example.com", "", "5.4.3.21") dnsServer, err := netem.NewDNSServer( &netem.NullLogger{}, dnsServerStack, "8.8.8.8", dnsConfig, ) if err != nil { log.Fatal(err) } defer dnsServer.Close() // spawn an HTTP server with the required configuration mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Bonsoir, Elliot!")) }) httpsAddr := &net.TCPAddr{ IP: net.ParseIP("5.4.3.21"), Port: 80, } httpsListener, err := httpsServerStack.ListenTCP("tcp", httpsAddr) if err != nil { log.Fatal(err) } httpsServer := &http.Server{ Handler: mux, } go httpsServer.Serve(httpsListener) defer httpsServer.Close() // create an HTTP transport using the clientStack txp := netem.NewHTTPTransport(clientStack) blockpage := []byte(`<html><head><title>451 Unavailable For Legal Reasons</title></head><body><center><h1>451 Unavailable For Legal Reasons</h1></center><p>This content is not available in your jurisdiction.</p></body></html>`) // add DPI rule that drops traffic for the www.example.com string dpi.AddRule(&netem.DPISpoofBlockpageForString{ HTTPResponse: netem.DPIFormatHTTPResponse(blockpage), Logger: apexlog.Log, ServerIPAddress: "5.4.3.21", ServerPort: 80, String: "www.example.com", }) // Note that all the code that follows is standard Go code that // would work for any implementation of http.RoundTripper. { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // create HTTP request req, err := http.NewRequestWithContext(ctx, "GET", "http://www.example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", string(respBody)) } { // create HTTP request req, err := http.NewRequest("GET", "http://example.com/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", string(respBody)) } }
Output: <html><head><title>451 Unavailable For Legal Reasons</title></head><body><center><h1>451 Unavailable For Legal Reasons</h1></center><p>This content is not available in your jurisdiction.</p></body></html> Bonsoir, Elliot!
Example (StarTopologyDNSWhoami) ¶
This example shows how DNS servers implement whoami.v4.powerdns.org
package main import ( "context" "fmt" "log" "github.com/ooni/netem" ) func main() { // Create a star topology for our hosts. topology := netem.MustNewStarTopology(&netem.NullLogger{}) defer topology.Close() // Add client stack to topology. Note that we don't need to // close the clientStack: the topology will do that. clientStack, err := topology.AddHost( "130.192.91.211", // host IP address "8.8.8.8", // host DNS resolver IP address &netem.LinkConfig{}, // link with no PLR, RTT, DPI ) if err != nil { log.Fatal(err) } // Add DNS server stack to topology. dnsServerStack, err := topology.AddHost( "8.8.8.8", "8.8.8.8", // this host is its own DNS resolver &netem.LinkConfig{}, ) if err != nil { log.Fatal(err) } // spawn a DNS server with empty configuration. dnsConfig := netem.NewDNSConfig() dnsServer, err := netem.NewDNSServer( &netem.NullLogger{}, dnsServerStack, "8.8.8.8", dnsConfig, ) if err != nil { log.Fatal(err) } defer dnsServer.Close() // create the DNS query to use query := netem.NewDNSRequestA("whoami.v4.powerdns.org") // issue a DNS request to the server response, err := netem.DNSRoundTrip(context.Background(), clientStack, "8.8.8.8", query) if err != nil { log.Fatal(err) } // parse the DNS response addrs, _, err := netem.DNSParseResponse(query, response) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", addrs) }
Output: [130.192.91.211]
Example (StarTopologyHTTPSAndDNS) ¶
This example shows how to create a star topology, a DNS server, and an HTTPS server. Then we create an HTTPS client and we use such a client to fetch a very important message from the server.
package main import ( "fmt" "io" "log" "net" "net/http" "github.com/ooni/netem" ) func main() { // Create a star topology for our hosts. topology := netem.MustNewStarTopology(&netem.NullLogger{}) defer topology.Close() // Add client stack to topology. Note that we don't need to // close the clientStack: the topology will do that. clientStack, err := topology.AddHost( "10.0.0.1", // host IP address "8.8.8.8", // host DNS resolver IP address &netem.LinkConfig{}, // link with no PLR, RTT, DPI ) if err != nil { log.Fatal(err) } // Add DNS server stack to topology. dnsServerStack, err := topology.AddHost( "8.8.8.8", "8.8.8.8", // this host is its own DNS resolver &netem.LinkConfig{}, ) if err != nil { log.Fatal(err) } // Add HTTPS server stack to topology. httpsServerStack, err := topology.AddHost( "5.4.3.21", "8.8.8.8", &netem.LinkConfig{}, ) if err != nil { log.Fatal(err) } // spawn a DNS server with the required configuration. dnsConfig := netem.NewDNSConfig() dnsConfig.AddRecord("tyrell.wellick.name", "tw01.fsociety.com.", "5.4.3.21") dnsServer, err := netem.NewDNSServer( &netem.NullLogger{}, dnsServerStack, "8.8.8.8", dnsConfig, ) if err != nil { log.Fatal(err) } defer dnsServer.Close() // spawn an HTTP server with the required configuration mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Bonsoir, Elliot!")) }) httpsAddr := &net.TCPAddr{ IP: net.ParseIP("5.4.3.21"), Port: 443, } httpsListener, err := httpsServerStack.ListenTCP("tcp", httpsAddr) if err != nil { log.Fatal(err) } httpsServer := &http.Server{ Handler: mux, TLSConfig: httpsServerStack.MustNewServerTLSConfig("tyrell.wellick.name"), } go httpsServer.ServeTLS(httpsListener, "", "") // empty string: use .TLSConfig defer httpsServer.Close() // create an HTTP transport using the clientStack txp := netem.NewHTTPTransport(clientStack) // Note that all the code that follows is standard Go code that // would work for any implementation of http.RoundTripper. // create HTTP request req, err := http.NewRequest("GET", "https://tyrell.wellick.name/", nil) if err != nil { log.Fatal(err) } // perform HTTP round trip resp, err := txp.RoundTrip(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() // read the response body data, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%d\n", resp.StatusCode) fmt.Printf("%s\n", string(data)) }
Output: 200 Bonsoir, Elliot!
Index ¶
- Constants
- Variables
- func DNSParseResponse(query, resp *dns.Msg) ([]string, string, error)
- func DNSRoundTrip(ctx context.Context, stack UnderlyingNetwork, ipAddress string, query *dns.Msg) (*dns.Msg, error)
- func DNSServerRoundTrip(config *DNSConfig, rawQuery []byte) ([]byte, error)
- func DPIFormatHTTPResponse(blockpage []byte) (output []byte)
- func ExtractTLSServerName(rawInput []byte) (string, error)
- func LinkFwdFast(cfg *LinkFwdConfig)
- func LinkFwdFull(cfg *LinkFwdConfig)
- func LinkFwdWithDelay(cfg *LinkFwdConfig)
- func Must0(err error)
- func Must1[Type any](value Type, err error) Type
- func Must2[A, B any](a A, b B, err error) (A, B)
- func NewDNSRequestA(domain string) *dns.Msg
- func NewHTTPTransport(stack HTTPUnderlyingNetwork) *http.Transport
- func RunNDT0Client(ctx context.Context, stack UnderlyingNetwork, serverAddr string, logger Logger, ...)
- func RunNDT0Server(ctx context.Context, stack UnderlyingNetwork, serverIPAddr net.IP, ...)
- func UnmarshalTLSServerNameExtension(cursor cryptobyte.String) (string, error)
- type CA
- func (ca *CA) CACert() *x509.Certificate
- func (ca *CA) DefaultCertPool() *x509.CertPool
- func (ca *CA) MustNewServerTLSConfig(commonName string, extraNames ...string) *tls.Config
- func (ca *CA) MustNewTLSCertificate(commonName string, extraNames ...string) *tls.Certificate
- func (ca *CA) MustNewTLSCertificateWithTimeNow(timeNow func() time.Time, commonName string, extraNames ...string) *tls.Certificate
- type CertificationAuthority
- type DNSConfig
- type DNSRecord
- type DNSServer
- type DPICloseConnectionForServerEndpoint
- type DPICloseConnectionForString
- type DPICloseConnectionForTLSSNI
- type DPIDirection
- type DPIDropTrafficForServerEndpoint
- type DPIDropTrafficForString
- type DPIDropTrafficForTLSSNI
- type DPIEngine
- type DPIPolicy
- type DPIResetTrafficForString
- type DPIResetTrafficForTLSSNI
- type DPIRule
- type DPISpoofBlockpageForString
- type DPISpoofDNSResponse
- type DPIThrottleTrafficForTCPEndpoint
- type DPIThrottleTrafficForTLSSNI
- type DissectedPacket
- func (dp *DissectedPacket) DecrementTimeToLive()
- func (dp *DissectedPacket) DestinationIPAddress() string
- func (dp *DissectedPacket) DestinationPort() uint16
- func (dp *DissectedPacket) FlowHash() uint64
- func (dp *DissectedPacket) MatchesDestination(proto layers.IPProtocol, address string, port uint16) bool
- func (dp *DissectedPacket) MatchesSource(proto layers.IPProtocol, address string, port uint16) bool
- func (dp *DissectedPacket) Serialize() ([]byte, error)
- func (dp *DissectedPacket) SourceIPAddress() string
- func (dp *DissectedPacket) SourcePort() uint16
- func (dp *DissectedPacket) TimeToLive() int64
- func (dp *DissectedPacket) TransportProtocol() layers.IPProtocol
- type ErrDial
- type Frame
- type FrameReader
- type HTTPUnderlyingNetwork
- type Link
- type LinkConfig
- type LinkFwdConfig
- type LinkFwdFunc
- type LinkFwdRNG
- type LinkNICWrapper
- type Logger
- type MockableNIC
- func (n *MockableNIC) Close() error
- func (n *MockableNIC) FrameAvailable() <-chan any
- func (n *MockableNIC) IPAddress() string
- func (n *MockableNIC) InterfaceName() string
- func (n *MockableNIC) ReadFrameNonblocking() (*Frame, error)
- func (n *MockableNIC) StackClosed() <-chan any
- func (n *MockableNIC) WriteFrame(frame *Frame) error
- type NDT0PerformanceSample
- type NIC
- type Net
- func (n *Net) DialContext(ctx context.Context, network, address string) (net.Conn, error)
- func (n *Net) DialTLSContext(ctx context.Context, network, address string) (net.Conn, error)
- func (n *Net) ListenTCP(network string, addr *net.TCPAddr) (net.Listener, error)
- func (n *Net) ListenTLS(network string, laddr *net.TCPAddr, config *tls.Config) (net.Listener, error)
- func (n *Net) ListenUDP(network string, addr *net.UDPAddr) (UDPLikeConn, error)
- func (n *Net) LookupCNAME(ctx context.Context, domain string) (string, error)
- func (n *Net) LookupHost(ctx context.Context, domain string) ([]string, error)
- type NullLogger
- type PCAPDumper
- type PPPTopology
- type ReadableNIC
- type Router
- type RouterPort
- func (sp *RouterPort) Close() error
- func (sp *RouterPort) FrameAvailable() <-chan any
- func (sp *RouterPort) IPAddress() string
- func (sp *RouterPort) InterfaceName() string
- func (sp *RouterPort) ReadFrameNonblocking() (*Frame, error)
- func (sp *RouterPort) StackClosed() <-chan any
- func (sp *RouterPort) WriteFrame(frame *Frame) error
- type StarTopology
- type StaticReadableNIC
- type StaticWriteableNIC
- type TLSClientHello
- type TLSExtension
- type TLSHandshakeMsg
- type TLSRecordHeader
- type UDPLikeConn
- type UNetStack
- func (gs *UNetStack) CACert() *x509.Certificate
- func (gs *UNetStack) Close() error
- func (gs *UNetStack) DefaultCertPool() *x509.CertPool
- func (gs *UNetStack) DialContext(ctx context.Context, network string, address string) (net.Conn, error)
- func (gs *UNetStack) FrameAvailable() <-chan any
- func (gs *UNetStack) GetaddrinfoLookupANY(ctx context.Context, domain string) ([]string, string, error)
- func (gs *UNetStack) GetaddrinfoResolverNetwork() string
- func (gs *UNetStack) IPAddress() string
- func (gs *UNetStack) InterfaceName() string
- func (gs *UNetStack) ListenTCP(network string, addr *net.TCPAddr) (net.Listener, error)
- func (gs *UNetStack) ListenUDP(network string, addr *net.UDPAddr) (UDPLikeConn, error)
- func (gs *UNetStack) Logger() Logger
- func (gs *UNetStack) MustNewServerTLSConfig(commonName string, extraNames ...string) *tls.Config
- func (gs *UNetStack) MustNewTLSCertificate(commonName string, extraNames ...string) *tls.Certificate
- func (gs *UNetStack) MustNewTLSCertificateWithTimeNow(timeNow func() time.Time, commonName string, extraNames ...string) *tls.Certificate
- func (gs *UNetStack) ReadFrameNonblocking() (*Frame, error)
- func (gs *UNetStack) StackClosed() <-chan any
- func (gs *UNetStack) WriteFrame(frame *Frame) error
- type UnderlyingNetwork
- type WriteableNIC
Examples ¶
Constants ¶
const ( // FrameFlagSpoof tells the router it should send the // spoofed frames inside the [Frame] Spoofed field. FrameFlagSpoof = 1 << iota // FrameFlagDrop tells the link that the frame should be // dropped rather than forwarded, to emulate a loss occurring // on the link while the frame was in flight. FrameFlagDrop )
const DPIDirectionClientToServer = DPIDirection(0)
DPIDirectionClientToServer is the direction from the client to the server. The client is the endpoint that sends the first packet in a flow.
const DPIDirectionServerToClient = DPIDirection(1)
DPIDirectionServerToClient is the direction from the server to the client. The client is the endpoint that sends the first packet in a flow.
const NDT0CSVHeader = "filename,rtt(s),plr,final,elapsed (s),total (byte),current (byte),avg speed (Mbit/s),cur speed (Mbit/s)"
NDT0CSVHeader is the header for the CSV records returned by the NDT0PerformanceSample.CSVRecord function.
Variables ¶
var ErrDNSNoAnswer = errors.New("netem: dns: no answer from DNS server")
ErrDNSNoAnswer is returned when the server response does not contain any answer for the original query (i.e., no IPv4 addresses).
var ErrDNSNoSuchHost = errors.New("netem: dns: no such host")
ErrDNSNoSuchHost is returned in case of NXDOMAIN.
var ErrDNSServerMisbehaving = errors.New("netem: dns: server misbehaving")
ErrDNSServerMisbehaving is the error we return for cases different from NXDOMAIN.
var ErrDissectNetwork = errors.New("netem: dissect: unsupported network protocol")
ErrDissectNetwork indicates that we do not support the packet's network protocol.
var ErrDissectShortPacket = errors.New("netem: dissect: packet too short")
ErrDissectShortPacket indicates the packet is too short.
var ErrDissectTransport = errors.New("netem: dissect: unsupported transport protocol")
ErrDissectTransport indicates that we do not support the packet's transport protocol.
var ErrDuplicateAddr = errors.New("netem: address has already been added")
ErrDuplicateAddr indicates that an address has already been added to a topology.
var ErrNoPacket = errors.New("netem: no packet in buffer")
ErrNoPacket indicates there's no packet ready.
var ErrNotIPAddress = errors.New("netem: not a valid IP address")
ErrNotIPAddress indicates that a string is not a serialized IP address.
var ErrPacketDropped = errors.New("netem: packet was dropped")
ErrPacketDropped indicates that a packet was dropped.
var ErrStackClosed = errors.New("netem: network stack closed")
ErrStackClosed indicates the network stack has been closed.
var ErrTLSParse = errors.New("tlsparse: parse error")
ErrTLSParse is the error returned in case there is a TLS parse error.
Functions ¶
func DNSParseResponse ¶
DNSParseResponse parses a dns.Msg into a getaddrinfo response
func DNSRoundTrip ¶
func DNSRoundTrip( ctx context.Context, stack UnderlyingNetwork, ipAddress string, query *dns.Msg, ) (*dns.Msg, error)
DNSRoundTrip performs a DNS round trip using a given UnderlyingNetwork.
func DNSServerRoundTrip ¶
DNSServerRoundTrip responds to a raw DNS query with a raw DNS response.
func DPIFormatHTTPResponse ¶
DPIFormatHTTPResponse formats an HTTP response for a blockpage.
func ExtractTLSServerName ¶
ExtractTLSServerName takes in input bytes read from the network, attempts to determine whether this is a TLS Handshale message, and if it is a ClientHello, and, if affirmative, attempts to extract the server name.
func LinkFwdFast ¶
func LinkFwdFast(cfg *LinkFwdConfig)
LinkFwdFast is the fast implementation of frames forwarding. We select this implementation when there are no configured losses, delay, or DPI.
func LinkFwdFull ¶
func LinkFwdFull(cfg *LinkFwdConfig)
LinkFwdFull is a full implementation of link forwarding that deals with delays, packet losses, and DPI.
The kind of half-duplex link modeled by this function will look much more like a shared geographical link than an ethernet link. For example, this link allows out-of-order delivery of packets.
func LinkFwdWithDelay ¶
func LinkFwdWithDelay(cfg *LinkFwdConfig)
LinkFwdWithDelay is an implementation of link forwarding that only delays packets without losses and deep packet inspection.
func NewDNSRequestA ¶
NewDNSRequestA creates a new A request.
func NewHTTPTransport ¶
func NewHTTPTransport(stack HTTPUnderlyingNetwork) *http.Transport
NewHTTPTransport creates a new http.Transport using an UnderlyingNetwork.
We fill the following fields of the transport:
- DialContext to call a dialing function that will eventually use stack.DialContext;
- DialTLSContext to use the stack's [MITMConfig];
- ForceAttemptHTTP2 to force enabling the HTTP/2 protocol.
func RunNDT0Client ¶
func RunNDT0Client( ctx context.Context, stack UnderlyingNetwork, serverAddr string, logger Logger, TLS bool, errch chan<- error, perfch chan<- *NDT0PerformanceSample, )
RunNDT0Client runs the NDT0 client nettest using the given server endpoint address and UnderlyingNetwork.
NDT0 is a stripped down NDT (network diagnostic tool) implementation where a client downloads from a server using a single stream.
The version number is zero because we use the network like ndt7 but we have much less implementation overhead.
This function prints on the standard output download speed information every 250 milliseconds using the CSV data format.
Arguments:
- ctx limits the overall measurement runtime;
- stack is the network stack to use;
- serverAddr is the server endpoint address (e.g., 10.0.0.1:443);
- logger is the logger to use;
- TLS controls whether we should use TLS;
- errch is the channel where we emit the overall error;
- perfch is the channel where we emit performance samples, which we close when we're done running.
func RunNDT0Server ¶
func RunNDT0Server( ctx context.Context, stack UnderlyingNetwork, serverIPAddr net.IP, serverPort int, logger Logger, ready chan<- net.Listener, errorch chan<- error, TLS bool, serverNames ...string, )
RunNDT0Server runs the NDT0 server. The server will listen for a single client connection and run until the client closes the connection.
You should run this function in a background goroutine.
Arguments:
- ctx limits the overall measurement runtime;
- stack is the network stack to use;
- serverIPAddr is the IP address where we should listen;
- serverPort is the TCP port where we should listen;
- logger is the logger to use;
- ready is the channel where we will post the listener once we have started listening: the caller OWNS the listener and is expected to close it when done or when the listener is stuck inside Accept and there is a need to interrupt it;
- errorch is where we post the overall result of this function (we will post a nil value in case of success);
- TLS controls whether we should use TLS;
- serverNames contains the SNIs to add to the certificate (TLS only).
func UnmarshalTLSServerNameExtension ¶
func UnmarshalTLSServerNameExtension(cursor cryptobyte.String) (string, error)
UnmarshalTLSServerNameExtension unmarshals the server name from the bytes that consist of the extension value.
Types ¶
type CA ¶
type CA struct {
// contains filtered or unexported fields
}
CA is a certification authority.
The zero value is invalid, please use [NewCA] to construct.
This code is derived from github.com/google/martian/v3.
SPDX-License-Identifier: Apache-2.0.
func MustNewCAWithTimeNow ¶
MustNewCA is like [NewCA] but uses a custom time.Now func.
This code is derived from github.com/google/martian/v3.
SPDX-License-Identifier: Apache-2.0.
func (*CA) CACert ¶
func (ca *CA) CACert() *x509.Certificate
CACert implements CertificationAuthority.
func (*CA) DefaultCertPool ¶
DefaultCertPool implements CertificationAuthority.
func (*CA) MustNewServerTLSConfig ¶
MustNewServerTLSConfig implements CertificationAuthority.
func (*CA) MustNewTLSCertificate ¶
func (ca *CA) MustNewTLSCertificate(commonName string, extraNames ...string) *tls.Certificate
MustNewTLSCertificate implements CertificationAuthority.
func (*CA) MustNewTLSCertificateWithTimeNow ¶
func (ca *CA) MustNewTLSCertificateWithTimeNow(timeNow func() time.Time, commonName string, extraNames ...string) *tls.Certificate
MustNewCertWithTimeNow implements CertificationAuthority.
This code is derived from github.com/google/martian/v3.
SPDX-License-Identifier: Apache-2.0.
type CertificationAuthority ¶
type CertificationAuthority interface { // CACert returns the CA certificate used by the server, which // allows you to add to an existing [*x509.CertPool]. CACert() *x509.Certificate // DefaultCertPool returns the default cert pool to use. DefaultCertPool() *x509.CertPool // MustNewServerTLSConfig constructs a server certificate for // the given common name and extra names, all of which could be // either IPv4/IPv6 addresses or domain names. MustNewServerTLSConfig(commonName string, extraNames ...string) *tls.Config // MustNewTLSCertificate constructs a TLS certificate for // the given common name and extra names, all of which could be // either IPv4/IPv6 addresses or domain names. MustNewTLSCertificate(commonName string, extraNames ...string) *tls.Certificate // MustNewTLSCertificateWithTimeNow is like MustNewTLSCertificate // but takes as input an explicit [time.Now] like func. MustNewTLSCertificateWithTimeNow(timeNow func() time.Time, commonName string, extraNames ...string) *tls.Certificate }
CertificationAuthority is a TLS certification authority.
type DNSConfig ¶
type DNSConfig struct {
// contains filtered or unexported fields
}
DNSConfig is the DNS configuration to use. The zero value is invalid; please use NewDNSConfig.
func (*DNSConfig) AddRecord ¶
AddRecord adds a record to the DNS server's database or returns an error.
func (*DNSConfig) RemoveRecord ¶
RemoveRecord removes a record from the DNS server's database. If the record does not exist, this method does nothing.
type DNSRecord ¶
type DNSRecord struct { // A is the A resource record. A []net.IP // CNAME is the CNAME. CNAME string }
DNSRecord is a DNS record in the DNSConfig.
type DNSServer ¶
type DNSServer struct {
// contains filtered or unexported fields
}
DNSServer is a DNS server. The zero value is invalid, please construct using NewDNSServer.
func NewDNSServer ¶
func NewDNSServer( logger Logger, stack UnderlyingNetwork, ipAddress string, config *DNSConfig, ) (*DNSServer, error)
NewDNSServer creates a new DNSServer instance. Remember to call DNSServer.Close when you are done using this server.
The ipAddress argument is the IPv4 DNS server address.
type DPICloseConnectionForServerEndpoint ¶
type DPICloseConnectionForServerEndpoint struct { // Logger is the MANDATORY logger. Logger Logger // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 }
DPICloseConnectionForServerEndpoint is a DPIRule that spoofs a FIN|ACK TCP segment after it sees a given TCP connect attempt. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
func (*DPICloseConnectionForServerEndpoint) Filter ¶
func (r *DPICloseConnectionForServerEndpoint) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPICloseConnectionForString ¶
type DPICloseConnectionForString struct { // Logger is the MANDATORY logger. Logger Logger // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 // SNI is the MANDATORY offending string. String string }
DPICloseConnectionForString is a DPIRule that spoofs a FIN|ACK TCP segment after it sees a given string in the payload. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
func (*DPICloseConnectionForString) Filter ¶
func (r *DPICloseConnectionForString) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPICloseConnectionForTLSSNI ¶
type DPICloseConnectionForTLSSNI struct { // Logger is the MANDATORY logger. Logger Logger // SNI is the MANDATORY offending SNI. SNI string }
DPICloseConnectionForTLSSNI is a DPIRule that spoofs a FIN|ACK TCP segment after it sees a given TLS SNI. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
func (*DPICloseConnectionForTLSSNI) Filter ¶
func (r *DPICloseConnectionForTLSSNI) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIDirection ¶
type DPIDirection int
DPIDirection is the direction of packets within a flow according to the DPIEngine.
type DPIDropTrafficForServerEndpoint ¶
type DPIDropTrafficForServerEndpoint struct { // Logger is the MANDATORY logger Logger Logger // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 // ServerProtocol is the MANDATORY server endpoint protocol. ServerProtocol layers.IPProtocol }
DPIDropTrafficForServerEndpoint is a DPIRule that drops all the traffic towards a given server endpoint. The zero value is invalid; please fill all the fields marked as MANDATORY.
func (*DPIDropTrafficForServerEndpoint) Filter ¶
func (r *DPIDropTrafficForServerEndpoint) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIDropTrafficForString ¶
type DPIDropTrafficForString struct { // Logger is the MANDATORY logger Logger Logger // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 // SNI is the MANDATORY string String string }
DPIDropTrafficForString is a DPIRule that drops all the traffic after it sees a given string. The zero value is invalid; please fill all the fields marked as MANDATORY.
func (*DPIDropTrafficForString) Filter ¶
func (r *DPIDropTrafficForString) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIDropTrafficForTLSSNI ¶
type DPIDropTrafficForTLSSNI struct { // Logger is the MANDATORY logger Logger Logger // SNI is the MANDATORY SNI SNI string }
DPIDropTrafficForTLSSNI is a DPIRule that drops all the traffic after it sees a given TLS SNI. The zero value is invalid; please fill all the fields marked as MANDATORY.
func (*DPIDropTrafficForTLSSNI) Filter ¶
func (r *DPIDropTrafficForTLSSNI) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIEngine ¶
type DPIEngine struct {
// contains filtered or unexported fields
}
DPIEngine is a deep packet inspection engine. The zero value is invalid; construct using NewDPIEngine.
func NewDPIEngine ¶
NewDPIEngine creates a new DPIEngine instance.
type DPIPolicy ¶
type DPIPolicy struct { // Delay is the extra delay to add to the packet. Delay time.Duration // Flags contains the flags to apply to the packet [Frame]. Flags int64 // PLR is the extra PLR to add to the packet. PLR float64 // Spoofed contains the spoofed frames to attach to // the [Frame] so that we emit spoofed packets in the // router when the frame is being processed. Spoofed [][]byte }
DPIPolicy tells the DPIEngine which policy to apply to a packet.
type DPIResetTrafficForString ¶
type DPIResetTrafficForString struct { // Logger is the MANDATORY logger. Logger Logger // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 // String is the MANDATORY offending string. String string }
DPIResetTrafficForString is a DPIRule that spoofs a RST TCP segment after it sees a given string in the payload for a given offending server endpoint. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
func (*DPIResetTrafficForString) Filter ¶
func (r *DPIResetTrafficForString) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIResetTrafficForTLSSNI ¶
type DPIResetTrafficForTLSSNI struct { // Logger is the MANDATORY logger. Logger Logger // SNI is the MANDATORY offending SNI. SNI string }
DPIResetTrafficForTLSSNI is a DPIRule that spoofs a RST TCP segment after it sees a given TLS SNI. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
func (*DPIResetTrafficForTLSSNI) Filter ¶
func (r *DPIResetTrafficForTLSSNI) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIRule ¶
type DPIRule interface {
Filter(direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
}
DPIRule is a deep packet inspection rule.
type DPISpoofBlockpageForString ¶
type DPISpoofBlockpageForString struct { // HTTPResponse is the MANDATORY blockpage content prefix with HTTP // headers (use DPIFormatHTTPResponse to produce this field). HTTPResponse []byte // Logger is the MANDATORY logger. Logger Logger // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 // SNI is the MANDATORY offending string. String string }
DPISpoofBlockpageForString is a DPIRule that spoofs a blockpage after it sees a given string in the payload. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
Note: this rule requires the blockpage to be very small.
func (*DPISpoofBlockpageForString) Filter ¶
func (r *DPISpoofBlockpageForString) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPISpoofDNSResponse ¶
type DPISpoofDNSResponse struct { // Addresses contains the OPTIONAL addresses to include // in the spoofed response. If this field is empty, we // will return a NXDOMAIN response to the user. Addresses []string // Logger is the MANDATORY logger. Logger Logger // Domain is the MANDATORY offending SNI. Domain string }
DPISpoofDNSResponse is a DPIRule that spoofs a DNS response after it sees a given DNS request. The zero value is invalid; please, fill all the fields marked as MANDATORY.
Note: this rule assumes that there is a router in the path that can generate a spoofed RST segment. If there is no router in the path, no RST segment will ever be generated.
Note: this rule relies on a race condition. For consistent results you MUST set some delay in the router<->server link.
func (*DPISpoofDNSResponse) Filter ¶
func (r *DPISpoofDNSResponse) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIThrottleTrafficForTCPEndpoint ¶
type DPIThrottleTrafficForTCPEndpoint struct { // Delay is the OPTIONAL extra delay to add to the flow. Delay time.Duration // Logger is the MANDATORY logger to use. Logger Logger // PLR is the OPTIONAL extra packet loss rate to apply to the packet. PLR float64 // ServerIPAddress is the MANDATORY server endpoint IP address. ServerIPAddress string // ServerPort is the MANDATORY server endpoint port. ServerPort uint16 }
DPIThrottleTrafficForTCPEndpoint is a DPIRule that throttles traffic for a given TCP endpoint. The zero value is not valid. Make sure you initialize all fields marked as MANDATORY.
func (*DPIThrottleTrafficForTCPEndpoint) Filter ¶
func (r *DPIThrottleTrafficForTCPEndpoint) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DPIThrottleTrafficForTLSSNI ¶
type DPIThrottleTrafficForTLSSNI struct { // Delay is the OPTIONAL extra delay to add to the flow. Delay time.Duration // Logger is the MANDATORY logger to use. Logger Logger // PLR is the OPTIONAL extra packet loss rate to apply to the packet. PLR float64 // SNI is the OPTIONAL offending SNI SNI string }
DPIThrottleTrafficForTLSSNI is a DPIRule that throttles traffic after it sees a given TLS SNI. The zero value is not valid. Make sure you initialize all fields marked as MANDATORY.
func (*DPIThrottleTrafficForTLSSNI) Filter ¶
func (r *DPIThrottleTrafficForTLSSNI) Filter( direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool)
Filter implements DPIRule
type DissectedPacket ¶
type DissectedPacket struct { // Packet is the underlying packet. Packet gopacket.Packet // IP is the network layer (either IPv4 or IPv6). IP gopacket.NetworkLayer // TCP is the POSSIBLY NIL tcp layer. TCP *layers.TCP // UDP is the POSSIBLY NIL UDP layer. UDP *layers.UDP }
DissectedPacket is a dissected IP packet. The zero-value is invalid; you MUST use the [dissectPacket] factory to create a new instance.
func DissectPacket ¶
func DissectPacket(rawPacket []byte) (*DissectedPacket, error)
DissectPacket parses a packet TCP/IP layers.
func (*DissectedPacket) DecrementTimeToLive ¶
func (dp *DissectedPacket) DecrementTimeToLive()
DecrementTimeToLive decrements the IPv4 or IPv6 time to live.
func (*DissectedPacket) DestinationIPAddress ¶
func (dp *DissectedPacket) DestinationIPAddress() string
DestinationIPAddress returns the packet's destination IP address.
func (*DissectedPacket) DestinationPort ¶
func (dp *DissectedPacket) DestinationPort() uint16
DestinationPort returns the packet's destination port.
func (*DissectedPacket) FlowHash ¶
func (dp *DissectedPacket) FlowHash() uint64
FlowHash returns the hash uniquely identifying the transport flow. Both directions of a flow will have the same hash.
func (*DissectedPacket) MatchesDestination ¶
func (dp *DissectedPacket) MatchesDestination(proto layers.IPProtocol, address string, port uint16) bool
MatchesDestination returns true when the given IPv4 packet has the expected protocol, destination address, and port.
func (*DissectedPacket) MatchesSource ¶
func (dp *DissectedPacket) MatchesSource(proto layers.IPProtocol, address string, port uint16) bool
MatchesSource returns true when the given IPv4 packet has the expected protocol, source address, and port.
func (*DissectedPacket) Serialize ¶
func (dp *DissectedPacket) Serialize() ([]byte, error)
Serialize serializes a previously dissected and modified packet.
func (*DissectedPacket) SourceIPAddress ¶
func (dp *DissectedPacket) SourceIPAddress() string
SourceIPAddress returns the packet's source IP address.
func (*DissectedPacket) SourcePort ¶
func (dp *DissectedPacket) SourcePort() uint16
SourcePort returns the packet's source port.
func (*DissectedPacket) TimeToLive ¶
func (dp *DissectedPacket) TimeToLive() int64
TimeToLive returns the packet's IPv4 or IPv6 time to live.
func (*DissectedPacket) TransportProtocol ¶
func (dp *DissectedPacket) TransportProtocol() layers.IPProtocol
TransportProtocol returns the packet's transport protocol.
type ErrDial ¶
type ErrDial struct { // Errors contains the list of errors. Errors []error }
ErrDial contains all the errors occurred during a [DialContext] operation.
type Frame ¶
type Frame struct { // Deadline is the time when this frame should be delivered. Deadline time.Time // Flags contains additional flags that [Router] will interpret // when processing this [Frame]. Flags int64 // Payload contains the packet payload. Payload []byte // Spoofed contains zero or more packets that the router should // spoof when processing this packet. We honor this field iff the // FrameFlagSpoof flag is set in the Flags field. Spoofed [][]byte }
Frame contains an IPv4 or IPv6 packet.
func (*Frame) ShallowCopy ¶
ShallowCopy creates a shallow copy of the Frame allowing us to modify its [Deadline] without data races risks.
type FrameReader ¶
type FrameReader interface { // FrameAvailable returns a channel that becomes readable // when a new frame has arrived. FrameAvailable() <-chan any // ReadFrameNonblocking reads an incoming frame. You should only call // this function after FrameAvailable has been readable. This function // returns one of the following errors: // // - ErrStackClosed if the underlying stack has been closed; // // - ErrNoPacket if no packet is available. // // Callers should ignore ErrNoPacket and try reading again later. ReadFrameNonblocking() (*Frame, error) // StackClosed returns a channel that becomes readable when the // userspace network stack has been closed. StackClosed() <-chan any }
FrameReader allows one to read incoming frames.
type HTTPUnderlyingNetwork ¶
type HTTPUnderlyingNetwork interface { UnderlyingNetwork IPAddress() string Logger() Logger }
HTTPUnderlyingNetwork is the UnderlyingNetwork used by HTTP code.
type Link ¶
type Link struct {
// contains filtered or unexported fields
}
Link models a link between a "left" and a "right" NIC. The zero value is invalid; please, use a constructor to create a new instance.
A link is characterized by left-to-right and right-to-left delays, which are configured by the Link constructors. A link is also characterized by a left-to-right and right-to-left packet loss rate (PLR).
Once you created a link, it will immediately start to forward traffic until you call Link.Close to shut it down.
func NewLink ¶
func NewLink(logger Logger, left, right NIC, config *LinkConfig) *Link
NewLink creates a new Link instance and spawns goroutines for forwarding traffic between the left and the right [LinkNIC]. You MUST call Link.Close to stop these goroutines when you are done with the Link.
NewLink selects the fastest link implementation that satisfies the provided config. Emulating PLR, RTT, and DPI has a cost, and it doesn't make sense to pay such a cost if you don't need them.
The returned Link TAKES OWNERSHIP of the left and right network stacks and ensures that their [Close] method is called when you call Link.Close.
type LinkConfig ¶
type LinkConfig struct { // DPIEngine is the OPTIONAL [DPIEngine]. DPIEngine *DPIEngine // LeftNICWrapper is the OPTIONAL [LinkNICWrapper] for the left NIC. LeftNICWrapper LinkNICWrapper // LeftToRightDelay is the OPTIONAL delay in the left->right direction. LeftToRightDelay time.Duration // LeftToRightPLR is the OPTIONAL packet-loss rate in the left->right direction. LeftToRightPLR float64 // RightNICWrapper is the OPTIONAL [LinkNICWrapper] for the right NIC. RightNICWrapper LinkNICWrapper // RightToLeftDelay is the OPTIONAL delay in the right->left direction. RightToLeftDelay time.Duration // RightToLeftPLR is the OPTIONAL packet-loss rate in the right->left direction. RightToLeftPLR float64 }
LinkConfig contains config for creating a Link.
type LinkFwdConfig ¶
type LinkFwdConfig struct { // DPIEngine is the OPTIONAL DPI engine. DPIEngine *DPIEngine // Logger is the MANDATORY logger. Logger Logger // NewLinkFwdRNG is an OPTIONAL factory that creates a new // random number generator, used for writing tests. NewLinkFwdRNG func() LinkFwdRNG // OneWayDelay is the OPTIONAL link one-way delay. OneWayDelay time.Duration // PLR is the OPTIONAL link packet-loss rate. PLR float64 // Reader is the MANDATORY [NIC] from which to read frames. Reader ReadableNIC // Writer is the MANDATORY [NIC] where to write frames. Writer WriteableNIC // Wg is MANDATORY the wait group that the frame forwarding goroutine // will notify when it is shutting down. Wg *sync.WaitGroup }
LinkFwdConfig contains config for frame forwarding algorithms. Make sure you initialize all the fields marked as MANDATORY.
type LinkFwdFunc ¶
type LinkFwdFunc func(cfg *LinkFwdConfig)
LinkFwdFunc is type type of a link forwarding function.
type LinkFwdRNG ¶
type LinkFwdRNG interface { // Float64 is like [rand.Rand.Float64]. Float64() float64 // Int63n is like [rand.Rand.Int63n]. Int63n(n int64) int64 }
LinkFwdRNG is a LinkFwdFunc view of a [rand.Rand] abstracted for festability.
type LinkNICWrapper ¶
LinkNICWrapper allows wrapping [NIC]s used by a Link to log packets, collect PCAPs and implement DPI.
type Logger ¶
type Logger interface { // Debugf formats and emits a debug message. Debugf(format string, v ...any) // Debug emits a debug message. Debug(message string) // Infof formats and emits an informational message. Infof(format string, v ...any) // Info emits an informational message. Info(message string) // Warnf formats and emits a warning message. Warnf(format string, v ...any) // Warn emits a warning message. Warn(message string) }
Logger is the logger we're using.
type MockableNIC ¶
type MockableNIC struct { // MockFrameAvailable allows mocking [NIC.FrameAvailable]. MockFrameAvailable func() <-chan any // MockReadFrameNonblocking allows mocking [NIC.ReadFrameNonblocking]. MockReadFrameNonblocking func() (*Frame, error) // MockStackClosed allows mocking [NIC.StackClosed]. MockStackClosed func() <-chan any // MockClose allows mocking [NIC.Close]. MockClose func() error // MockIPAddress allows mocking [NIC.IPAddress]. MockIPAddress func() string // MockInterfaceName allows mocking [NIC.InterfaceName]. MockInterfaceName func() string // MockWriteFrame allows mocking [NIC.WriteFrame]. MockWriteFrame func(frame *Frame) error }
MocakbleNIC is a mockable NIC implementation.
func (*MockableNIC) FrameAvailable ¶
func (n *MockableNIC) FrameAvailable() <-chan any
FrameAvailable implements NIC
func (*MockableNIC) InterfaceName ¶
func (n *MockableNIC) InterfaceName() string
InterfaceName implements NIC
func (*MockableNIC) ReadFrameNonblocking ¶
func (n *MockableNIC) ReadFrameNonblocking() (*Frame, error)
ReadFrameNonblocking implements NIC
func (*MockableNIC) StackClosed ¶
func (n *MockableNIC) StackClosed() <-chan any
StackClosed implements NIC
func (*MockableNIC) WriteFrame ¶
func (n *MockableNIC) WriteFrame(frame *Frame) error
WriteFrame implements NIC
type NDT0PerformanceSample ¶
type NDT0PerformanceSample struct { // Final indicates whether this is the final sample. Final bool // ReceivedTotal is the total number of bytes received. ReceivedTotal int64 // ReceivedLast is the total number of bytes received since // we collected the last sample. ReceivedLast int64 // TimeLast is the last time we collected a sample. TimeLast time.Time // TimeNow is the time when we collected this sample. TimeNow time.Time // TimeZero is when the measurement started. TimeZero time.Time }
NDT0PerformanceSample is a performance sample returned by RunNDT0Client.
func (*NDT0PerformanceSample) AvgSpeedMbps ¶
func (ps *NDT0PerformanceSample) AvgSpeedMbps() float64
AvgSpeedMbps returns the average speed since the beginning of the measurement expressed in Mbit/s.
func (*NDT0PerformanceSample) ElapsedSeconds ¶
func (ps *NDT0PerformanceSample) ElapsedSeconds() float64
ElapsedSeconds returns the elapsed time since the beginning of the measurement expressed in seconds.
type NIC ¶
type NIC interface { // A NIC implements FrameReader FrameReader // Close closes this network interface. Close() error // IPAddress returns the IP address assigned to the NIC. IPAddress() string // InterfaceName returns the name of the NIC. InterfaceName() string // WriteFrame writes a frame or returns an error. This function // returns ErrStackClosed when the underlying stack has been closed. WriteFrame(frame *Frame) error }
NIC is a network interface card with which you can send and receive [Frame]s.
type Net ¶
type Net struct { // Stack is the MANDATORY underlying stack. Stack UnderlyingNetwork }
Net is a drop-in replacement for the net package. The zero value is invalid; please init all the MANDATORY fields.
func (*Net) DialContext ¶
DialContext is a drop-in replacement for net.Dialer.DialContext.
func (*Net) DialTLSContext ¶
DialTLSContext is like Net.DialContext but also performs a TLS handshake.
func (*Net) ListenTCP ¶
ListenTCP is a drop-in replacement for net.ListenTCP.
func (*Net) ListenTLS ¶
func (n *Net) ListenTLS(network string, laddr *net.TCPAddr, config *tls.Config) (net.Listener, error)
ListenTLS is a replacement for tls.Listen that uses the underlying stack's TLS MITM capabilities during the TLS handshake.
func (*Net) ListenUDP ¶
ListenUDP is a drop-in replacement for net.ListenUDP.
func (*Net) LookupCNAME ¶
LookupCNAME is a drop-in replacement for net.Resolver.LookupCNAME.
func (*Net) LookupHost ¶
LookupHost is a drop-in replacement for net.Resolver.LookupHost.
type NullLogger ¶
type NullLogger struct{}
NullLogger is a netem.Logger that does not emit logs.
func (*NullLogger) Debug ¶
func (nl *NullLogger) Debug(message string)
Debug implements netem.Logger
func (*NullLogger) Debugf ¶
func (nl *NullLogger) Debugf(format string, v ...any)
Debugf implements netem.Logger
func (*NullLogger) Infof ¶
func (nl *NullLogger) Infof(format string, v ...any)
Infof implements netem.Logger
func (*NullLogger) Warnf ¶
func (nl *NullLogger) Warnf(format string, v ...any)
Warnf implements netem.Logger
type PCAPDumper ¶
type PCAPDumper struct {
// contains filtered or unexported fields
}
PCAPDumper collects a PCAP trace. The zero value is invalid and you should use NewPCAPDumper to instantiate. Once you have a valid instance, you should register the PCAPDumper as a LinkNICWrapper inside the LinkConfig.
func NewPCAPDumper ¶
func NewPCAPDumper(filename string, logger Logger) *PCAPDumper
NewPCAPDumper creates a new PCAPDumper.
func (*PCAPDumper) WrapNIC ¶
func (pd *PCAPDumper) WrapNIC(nic NIC) NIC
WrapNIC implements the LinkNICWrapper interface.
type PPPTopology ¶
type PPPTopology struct { // Client is the client network stack in the PPP topology. Client *UNetStack // Server is the server network stack in the PPP topology. Server *UNetStack // contains filtered or unexported fields }
PPPTopology is a point-to-point topology with two network stacks and a Link in the middle. By convention, the left stack is the client and the right one is the server. The zero value of this struct is invalid; use [NewPPPTopology] to create a new instance.
func MustNewPPPTopology ¶
func MustNewPPPTopology( clientAddress string, serverAddress string, logger Logger, lc *LinkConfig, ) *PPPTopology
MustNewPPPTopology creates a PPPTopology. Use the Close method to shutdown the link created by this topology.
Arguments:
- clientAddress is the client IP address;
- serverAddress is the server IP address;
- logger is the logger to use;
- MTU is the MTU to use (1500 is a good MTU value);
- lc describes the link characteristics.
func (*PPPTopology) Close ¶
func (t *PPPTopology) Close() error
Close closes all the hosts and links allocated by the topology
type ReadableNIC ¶
type ReadableNIC interface { FrameReader InterfaceName() string }
ReadableNIC is the read-only NIC used by frame forwarding algorithms.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router routes traffic between [RouterPort]s. The zero value of this structure isn't invalid; construct using NewRouter.
func (*Router) AddRoute ¶
func (r *Router) AddRoute(destIP string, destPort *RouterPort)
AddRoute adds a route to the routing table.
type RouterPort ¶
type RouterPort struct {
// contains filtered or unexported fields
}
RouterPort is a port of a Router. The zero value is invalid, use the NewRouterPort constructor to instantiate.
func NewRouterPort ¶
func NewRouterPort(router *Router) *RouterPort
NewRouterPort creates a new RouterPort for a given Router.
func (*RouterPort) FrameAvailable ¶
func (sp *RouterPort) FrameAvailable() <-chan any
FrameAvailable implements NIC
func (*RouterPort) InterfaceName ¶
func (sp *RouterPort) InterfaceName() string
InterfaceName implements NIC
func (*RouterPort) ReadFrameNonblocking ¶
func (sp *RouterPort) ReadFrameNonblocking() (*Frame, error)
ReadFrameNonblocking implements NIC
func (*RouterPort) StackClosed ¶
func (sp *RouterPort) StackClosed() <-chan any
StackClosed implements NIC
func (*RouterPort) WriteFrame ¶
func (sp *RouterPort) WriteFrame(frame *Frame) error
WriteFrame implements NIC
type StarTopology ¶
type StarTopology struct {
// contains filtered or unexported fields
}
StarTopology is the star network topology: there is a router in the middle and all hosts connect to it. The zero value is invalid; please, construct using the [NewStarTopology].
func MustNewStarTopology ¶
func MustNewStarTopology(logger Logger) *StarTopology
MustNewStarTopology constructs a new, empty StarTopology consisting of a Router sitting in the middle. Once you have the StarTopology you can now add hosts using [AddHost], [AddHTTPServer], etc.
func (*StarTopology) AddHost ¶
func (t *StarTopology) AddHost( hostAddress string, resolverAddress string, lc *LinkConfig, ) (*UNetStack, error)
AddHost creates a new UNetStack and a RouterPort, creates a Link to connect them, attaches the port to the topology's Router, and returns the UNetStack to the caller. You do not need to call [Close] for the returned UNetStack because calling the [StartTopology]'s Close method will also close the UNetStack.
Arguments:
- hostAddress is the IPv4 address to assign to the UNetStack;
- resolverAddress is the IPv4 address of the resolver the UNetStack should use; use 0.0.0.0 if you don't need DNS resolution;
- lc contains config for the Link connecting the UNetStack to the Router of the StarTopology.
func (*StarTopology) Close ¶
func (t *StarTopology) Close() error
Close closes (a) the router and (b) all the links and the hosts created using this StarTopology.
type StaticReadableNIC ¶
type StaticReadableNIC struct {
// contains filtered or unexported fields
}
StaticReadableNIC is a ReadableNIC that will return a fixed amount of frames. The zero value is invalid; use NewStaticReadableNIC factory to construct an instance. Remember to call CloseNetworkStack when you have read all the frames emitted by a channel to unblock the stack.
func NewStaticReadableNIC ¶
func NewStaticReadableNIC(name string, frames ...*Frame) *StaticReadableNIC
NewStaticReadableNIC constructs a new StaticReadableNIC instance.
func (*StaticReadableNIC) CloseNetworkStack ¶
func (n *StaticReadableNIC) CloseNetworkStack()
CloseNetworkStack closes the network stack used by this NIC, which in turn causes StackClosed() to become readable.
func (*StaticReadableNIC) FrameAvailable ¶
func (n *StaticReadableNIC) FrameAvailable() <-chan any
FrameAvailable implements ReadableNIC
func (*StaticReadableNIC) InterfaceName ¶
func (n *StaticReadableNIC) InterfaceName() string
InterfaceName implements ReadableNIC
func (*StaticReadableNIC) ReadFrameNonblocking ¶
func (n *StaticReadableNIC) ReadFrameNonblocking() (*Frame, error)
ReadFrameNonblocking implements ReadableNIC
func (*StaticReadableNIC) StackClosed ¶
func (n *StaticReadableNIC) StackClosed() <-chan any
StackClosed implements ReadableNIC
type StaticWriteableNIC ¶
type StaticWriteableNIC struct {
// contains filtered or unexported fields
}
StaticWriteableNIC is a [WritableNIC] that collects all the frames it received for you to inspect later. The zero value is invalid; construct using [NewStaticWritableNIC].
func NewStaticWriteableNIC ¶
func NewStaticWriteableNIC(name string) *StaticWriteableNIC
NewStaticWriteableNIC constructs a new StaticWriteableNIC instance.
func (*StaticWriteableNIC) Frames ¶
func (n *StaticWriteableNIC) Frames() <-chan *Frame
Frames returns the channel where we post frames
func (*StaticWriteableNIC) InterfaceName ¶
func (n *StaticWriteableNIC) InterfaceName() string
InterfaceName implements WriteableNIC
func (*StaticWriteableNIC) WriteFrame ¶
func (n *StaticWriteableNIC) WriteFrame(frame *Frame) error
WriteFrame implements WriteableNIC
type TLSClientHello ¶
type TLSClientHello struct { // ProtocolVersion is the protocol version. ProtocolVersion uint16 // Random contains exacty 32 bytes of random data. Random []byte // LegacySessionID is the legacy session ID. LegacySessionID cryptobyte.String // CipherSuites contains the client cipher suites. CipherSuites cryptobyte.String // LegacyCompressionMethods contains the legacy compression methods. LegacyCompressionMethods cryptobyte.String // Extensions contains the extensions. Extensions cryptobyte.String }
TLSClientHello is the TLSClientHello message.
type TLSExtension ¶
type TLSExtension struct { // Type is the extension type. Type uint16 // Data contains the extension data. Data cryptobyte.String }
TLSExtension is a TLS extension.
func FindTLSServerNameExtension ¶
func FindTLSServerNameExtension(exts []*TLSExtension) (*TLSExtension, bool)
FindTLSServerNameExtension returns the first ServerName extension in case of success or false in case of failure.
func UnmarshalTLSExtensions ¶
func UnmarshalTLSExtensions(cursor cryptobyte.String) ([]*TLSExtension, error)
UnmarshalTLSExtensions unmarshals the extensions.
Return value:
1. the parsed []*Extensions (on success);
2. an error (nil on success).
type TLSHandshakeMsg ¶
type TLSHandshakeMsg struct { // HandshakeType is the type of handshake message. HandshakeType uint8 // ClientHello is either nil or the parsed ClientHello. ClientHello *TLSClientHello }
TLSHandshakeMsg is the TLSHandshakeMsg message.
func UnmarshalTLSHandshakeMsg ¶
func UnmarshalTLSHandshakeMsg(cursor cryptobyte.String) (*TLSHandshakeMsg, error)
UnmarshalTLSHandshakeMsg unmarshals an Handshake message.
Return value:
1. the parsed Handshake (on success);
2. an error (nil on success).
type TLSRecordHeader ¶
type TLSRecordHeader struct { // ContentType is the type of the content. ContentType uint8 // ProtocolVersion is the version of the TLS protocol. ProtocolVersion uint16 // Rest contains the rest of the message. Rest cryptobyte.String }
TLSRecordHeader is a TLS TLSRecordHeader.
func UnmarshalTLSRecordHeader ¶
func UnmarshalTLSRecordHeader(cursor cryptobyte.String) (*TLSRecordHeader, cryptobyte.String, error)
UnmarshalTLSRecordHeader unmarshals a RecordHeader.
Return value:
1. the parsed RecordHeader (on success);
2. the unparsed bytes (on success), which may be empty if the input only contained a whole RecordHeader;
3. an error (nil on success).
type UDPLikeConn ¶
type UDPLikeConn interface { // An UDPLikeConn is a net.PacketConn conn. net.PacketConn // SetReadBuffer allows setting the read buffer. SetReadBuffer(bytes int) error // SyscallConn returns a conn suitable for calling syscalls, // which is also instrumental to setting the read buffer. SyscallConn() (syscall.RawConn, error) }
UDPLikeConn is a net.PacketConn with some extra functions required to convince the QUIC library (lucas-clemente/quic-go) to inflate the receive buffer of the connection.
The QUIC library will treat this connection as a "dumb" net.PacketConn, calling its ReadFrom and WriteTo methods as opposed to more efficient methods that are available under Linux and (maybe?) FreeBSD.
It seems fine to avoid performance optimizations, because they would complicate the implementation on our side and our use cases (blocking and heavy throttling) do not seem to require such optimizations.
See https://github.com/ooni/probe/issues/1754 for a more comprehensive discussion of UDPLikeConn.
type UNetStack ¶
type UNetStack struct {
// contains filtered or unexported fields
}
UNetStack is a network stack in user space. The zero value is invalid; please, use NewUNetStack to construct.
Because UNetStack implements UnderlyingNetwork, you can use it to perform the following operations:
- connect TCP/UDP sockets using UNetStack.DialContext;
- create listening UDP sockets using UNetStack.ListenUDP;
- create listening TCP sockets using UNetStack.ListenTCP;
- perform getaddrinfo like DNS lookups using UNetStack.GetaddrinfoLookupANY;
Use [UNetStack.NIC] to obtain a NIC to read and write the [Frames] produced by using the network stack as the UnderlyingNetwork.
func NewUNetStack ¶
func NewUNetStack( logger Logger, MTU uint32, stackAddress string, ca *CA, resolverAddress string, ) (*UNetStack, error)
NewUNetStack constructs a new UNetStack instance.
Arguments:
- logger is the logger to use;
- MTU is the MTU to use (you MUST use at least 1252 bytes if you want to use github.com/lucas-clemente/quic-go);
- stackAddress is the IPv4 address to assign to the stack;
- cfg contains TLS MITM configuration;
- resolverAddress is the IPv4 address of the resolver.
func (*UNetStack) CACert ¶
func (gs *UNetStack) CACert() *x509.Certificate
CACert implements CertificationAuthority.
func (*UNetStack) DefaultCertPool ¶
DefaultCertPool implements CertificationAuthority.
func (*UNetStack) DialContext ¶
func (gs *UNetStack) DialContext( ctx context.Context, network string, address string) (net.Conn, error)
DialContext implements UnderlyingNetwork.
func (*UNetStack) FrameAvailable ¶
FrameAvailable implements NIC
func (*UNetStack) GetaddrinfoLookupANY ¶
func (gs *UNetStack) GetaddrinfoLookupANY(ctx context.Context, domain string) ([]string, string, error)
GetaddrinfoLookupANY implements UnderlyingNetwork.
func (*UNetStack) GetaddrinfoResolverNetwork ¶
GetaddrinfoResolverNetwork implements UnderlyingNetwork
func (*UNetStack) InterfaceName ¶
InterfaceName implements NIC
func (*UNetStack) MustNewServerTLSConfig ¶
MustNewServerTLSConfig implements CertificationAuthority.
func (*UNetStack) MustNewTLSCertificate ¶
func (gs *UNetStack) MustNewTLSCertificate(commonName string, extraNames ...string) *tls.Certificate
MustNewTLSCertificate implements implements CertificationAuthority.
func (*UNetStack) MustNewTLSCertificateWithTimeNow ¶
func (gs *UNetStack) MustNewTLSCertificateWithTimeNow(timeNow func() time.Time, commonName string, extraNames ...string) *tls.Certificate
MustNewTLSCertificateWithTimeNow implements CertificationAuthority.
func (*UNetStack) ReadFrameNonblocking ¶
ReadFrameNonblocking implements NIC
func (*UNetStack) StackClosed ¶
StackClosed implements NIC
func (*UNetStack) WriteFrame ¶
WriteFrame implements NIC
type UnderlyingNetwork ¶
type UnderlyingNetwork interface { // CertificationAuthority allows accessing the certification authority // associated with this host or set of hosts. CertificationAuthority // DialContext dials a TCP or UDP connection. Unlike [net.DialContext], this // function does not implement dialing when address contains a domain. DialContext(ctx context.Context, network, address string) (net.Conn, error) // GetaddrinfoLookupANY is like [net.Resolver.LookupHost] except that it // also returns to the caller the CNAME when it is available. GetaddrinfoLookupANY(ctx context.Context, domain string) ([]string, string, error) // GetaddrinfoResolverNetwork returns the resolver network. GetaddrinfoResolverNetwork() string // ListenTCP creates a new listening TCP socket. ListenTCP(network string, addr *net.TCPAddr) (net.Listener, error) // ListenUDP creates a new listening UDP socket. The [UDPLikeConn] returned // by this function is a best effort attempt to emulate a [net.UDPConn] that // works with the github.com/lucas-clemente/quic-go library. ListenUDP(network string, addr *net.UDPAddr) (UDPLikeConn, error) }
UnderlyingNetwork replaces for functions in the net package.