connectip

package module
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 31 Imported by: 10

README

Proxying IP over HTTP

PkgGoDev Code Coverage Fuzzing Status

connect-ip-go is an implementation of the CONNECT-IP protocol RFC 9484, allowing the proxying of IP packets in HTTP/3.

It is based on quic-go, and provides both a client and a proxy implementation.

It also implements draft-ietf-masque-connect-ip-dns-07, which adds DNS and PREF64 configuration to CONNECT-IP.

At this point, it supports the following use cases:

Release Policy

connect-ip-go always aims to support the latest two Go releases.

Contributing

We are always happy to welcome new contributors! If you have any questions, please feel free to reach out by opening an issue or leaving a comment.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AddressRequest added in v0.4.0

type AddressRequest struct {
	Prefixes []netip.Prefix
	// contains filtered or unexported fields
}

AddressRequest is a request received from the peer. The zero value is not valid.

func (*AddressRequest) Respond added in v0.4.0

func (r *AddressRequest) Respond(assignments, additional []netip.Prefix) error

Respond queues the complete address assignment for the peer. Assignments must have one entry per original requested prefix, in the same order. A zero-value netip.Prefix rejects that request. Additional contains any other valid prefixes to include, with request ID zero. All prefixes must have their host bits cleared. A request can be answered only once.

type AddressRequestID added in v0.4.0

type AddressRequestID uint64

AddressRequestID identifies an address request. Zero denotes an unsolicited assignment.

type AssignedAddress

type AssignedAddress struct {
	// RequestID is zero for an unsolicited assignment.
	RequestID AddressRequestID
	IPPrefix  netip.Prefix
}

AssignedAddress represents an Assigned Address within an ADDRESS_ASSIGN capsule

func (AssignedAddress) Rejected added in v0.4.0

func (a AssignedAddress) Rejected() bool

Rejected reports whether the assignment is a refusal (0.0.0.0/32 or ::/128).

type ClientConn added in v0.3.0

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

A ClientConn represents a connection to a single proxy server. Multiple proxied connections can be established over a single ClientConn.

func NewClientConn added in v0.4.0

func NewClientConn(conn *http3.ClientConn) *ClientConn

NewClientConn creates a client connection using an existing HTTP/3 connection. The HTTP/3 connection and its underlying QUIC connection must have datagrams enabled. The caller owns the HTTP/3 connection and can also use it for ordinary HTTP requests. Closing a Conn returned by ClientConn.Dial does not close the HTTP/3 connection.

func (*ClientConn) Dial added in v0.3.0

func (c *ClientConn) Dial(req *Request) (*Conn, *http.Response, error)

Dial dials a proxied connection over the proxy connection.

type CloseError

type CloseError struct {
	Remote bool
}

func (*CloseError) Error

func (e *CloseError) Error() string

func (*CloseError) Is

func (e *CloseError) Is(target error) bool

type Conn

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

Conn is a connection that proxies IP packets over HTTP/3.

func (*Conn) AdvertiseRoute

func (c *Conn) AdvertiseRoute(routes []IPRoute) error

AdvertiseRoute schedules an advertisement of the available routes to the peer. It returns once the advertisement has been queued.

func (*Conn) AssignAddresses

func (c *Conn) AssignAddresses(prefixes []netip.Prefix) error

AssignAddresses schedules an assignment of address prefixes to the peer. A nil or empty slice removes all assigned addresses.

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) ReadPacket

func (c *Conn) ReadPacket(b []byte) (n int, err error)

func (*Conn) ReceiveAddressAssignment added in v0.4.0

func (c *Conn) ReceiveAddressAssignment(ctx context.Context) ([]AssignedAddress, error)

ReceiveAddressAssignment waits for the next complete address assignment, Each assignment replaces the preceding one; request IDs only provide optional correlation. Call this method in a loop from one goroutine.

func (*Conn) ReceiveAddressRequest added in v0.4.0

func (c *Conn) ReceiveAddressRequest(ctx context.Context) (*AddressRequest, error)

ReceiveAddressRequest waits for the next address request from the peer. This method should be called in a loop, and each request should be answered with AddressRequest.Respond.

func (*Conn) ReceiveDNSConfiguration added in v0.3.0

func (c *Conn) ReceiveDNSConfiguration(ctx context.Context) ([]DNSConfiguration, error)

ReceiveDNSConfiguration waits for the next DNS configuration update from the peer. Each update supersedes the preceding one.

func (*Conn) ReceivePREF64Configuration added in v0.3.0

func (c *Conn) ReceivePREF64Configuration(ctx context.Context) ([]netip.Prefix, error)

ReceivePREF64Configuration waits for the next NAT64 prefix update from the peer. An empty slice means that NAT64 prefixes are not available.

func (*Conn) RequestAddresses added in v0.4.0

func (c *Conn) RequestAddresses(prefixes []netip.Prefix) ([]AddressRequestID, error)

RequestAddresses requests address prefixes from the peer and returns once the request is queued. It allocates a unique, nonzero ID for each prefix in input order. The IDs have no semantic meaning and can be used to correlate assignments returned by Conn.ReceiveAddressAssignment with the requested prefixes.

Prefixes must be valid, with all bits outside the prefix set to zero. An unspecified address (0.0.0.0 or ::) requests any address of that family, with the prefix length indicating the preferred size.

func (*Conn) Routes

func (c *Conn) Routes(ctx context.Context) ([]IPRoute, error)

Routes returns the routes that the peer currently advertised. Note that at any point during the connection, the peer can change the advertised routes. It is therefore recommended to call this function in a loop.

func (*Conn) SendDNSConfiguration added in v0.3.0

func (c *Conn) SendDNSConfiguration(configurations []DNSConfiguration) error

SendDNSConfiguration schedules a DNS configuration update to the peer. The update supersedes the DNS configuration previously sent on this connection.

To avoid leaking DNS traffic outside the tunnel, the application is responsible for advertising the corresponding routes before calling this method. See Section 5 of draft-ietf-masque-connect-ip-dns-06.

func (*Conn) SendPREF64Configuration added in v0.3.0

func (c *Conn) SendPREF64Configuration(prefixes []netip.Prefix) error

SendPREF64Configuration schedules an update of the NAT64 prefixes to use for IPv6/IPv4 address synthesis. It returns once the update has been queued. An empty slice clears the previously sent configuration.

func (*Conn) WritePacket

func (c *Conn) WritePacket(b []byte) (icmp []byte, err error)

WritePacket writes an IP packet to the stream. The packet is dropped unless its destination was assigned to the peer or matches one of the peer's routes. If the peer assigned addresses to us, the source address needs to be one of these addresses, or be covered by one of the routes that we advertised. If sending the packet fails, it might return an ICMP packet. It is the caller's responsibility to send the ICMP packet to the sender.

type DNSConfiguration added in v0.3.0

type DNSConfiguration struct {
	// Nameservers must not be empty.
	Nameservers []DNSNameserver
	// InternalDomains contains fully qualified domain names, without the trailing
	// root dot and using IDNA A-labels. An empty string represents the DNS root.
	InternalDomains []string
	// SearchDomains contains fully qualified domain names, without the trailing
	// root dot and using IDNA A-labels.
	SearchDomains []string
}

DNSConfiguration describes the DNS Configuration structure defined by draft-ietf-masque-connect-ip-dns-06.

type DNSNameserver added in v0.3.0

type DNSNameserver struct {
	ServicePriority uint16
	IPv4Addresses   []netip.Addr
	// IPv6Addresses must not contain scoped addressing zones.
	// Zone identifiers are local to an endpoint and are not part of the wire format.
	IPv6Addresses []netip.Addr
	// AuthenticationDomainName is the fully qualified domain name of the
	// nameserver, without the trailing root dot and using IDNA A-labels. It may be
	// empty only when the nameserver supports unencrypted DNS exclusively.
	AuthenticationDomainName string
	// ServiceParameters is the set of SVCB parameters that apply to this nameserver.
	// Each map value is the wire-format SvcParamValue for its key.
	ServiceParameters map[dnsmessage.SVCParamKey][]byte
}

DNSNameserver describes the Nameserver structure defined by draft-ietf-masque-connect-ip-dns-06.

type IPRoute

type IPRoute struct {
	StartIP netip.Addr
	EndIP   netip.Addr
	// IPProtocol is the Internet Protocol Number for traffic that can be sent to this range.
	// If the value is 0, all protocols are allowed.
	IPProtocol uint8
}

IPRoute represents an IP Address Range

func (IPRoute) Prefixes

func (r IPRoute) Prefixes() []netip.Prefix

Prefixes returns the prefixes that this IP address range covers. Note that depending on the start and end addresses, this conversion can result in a large number of prefixes.

type Proxy

type Proxy struct{}

func (*Proxy) Proxy

func (s *Proxy) Proxy(w http.ResponseWriter, _ *ProxyRequest) (*Conn, error)

type ProxyRequest added in v0.3.0

type ProxyRequest struct{}

ProxyRequest is the parsed CONNECT-IP request returned from ParseProxyRequest. It currently doesn't have any fields, since connect-ip-go doesn't support IP flow forwarding.

func ParseProxyRequest added in v0.3.0

func ParseProxyRequest(r *http.Request, template *uritemplate.Template) (*ProxyRequest, error)

ParseProxyRequest parses a CONNECT-IP request. The template is the URI template that clients will use to configure this proxy.

type ProxyRequestParseError added in v0.3.0

type ProxyRequestParseError struct {
	HTTPStatus int
	Err        error
}

ProxyRequestParseError is returned from ParseProxyRequest if parsing the CONNECT-IP request fails. It is recommended that the request is rejected with the corresponding HTTP status code.

func (*ProxyRequestParseError) Error added in v0.3.0

func (e *ProxyRequestParseError) Error() string

func (*ProxyRequestParseError) Unwrap added in v0.3.0

func (e *ProxyRequestParseError) Unwrap() error

type Request

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

Request is a CONNECT-IP request created by NewRequest. The zero value is not valid.

func NewRequest added in v0.3.0

func NewRequest(ctx context.Context, proxyTemplate *uritemplate.Template) (*Request, error)

NewRequest creates a CONNECT-IP request.

func (*Request) Header added in v0.3.0

func (r *Request) Header() http.Header

Header returns the HTTP header fields sent with the CONNECT-IP request. Callers may add custom headers before dialing.

type Transport added in v0.3.0

type Transport struct {
	// TLSClientConfig is the TLS client config used when dialing the QUIC connection to the proxy.
	// It must set the "h3" ALPN.
	TLSClientConfig *tls.Config

	// QUICConfig is the QUIC config used when dialing the QUIC connection.
	QUICConfig *quic.Config

	// DialAddr dials the QUIC connection to the proxy.
	// If unset, quic.DialAddr is used.
	DialAddr func(ctx context.Context, addr string, tlsConf *tls.Config, quicConf *quic.Config) (*quic.Conn, error)
}

A Transport establishes proxied connections to multiple proxy servers.

func (*Transport) Dial added in v0.3.0

func (t *Transport) Dial(req *Request) (*Conn, *http.Response, error)

Dial opens a QUIC connection to the proxy and then dials a proxied connection. Closing the returned Conn also closes the QUIC connection to the proxy. To establish multiple proxied connections over one proxy connection, use Transport.NewClientConn.

func (*Transport) NewClientConn added in v0.3.0

func (t *Transport) NewClientConn(conn *quic.Conn) (*ClientConn, error)

NewClientConn creates a client connection for an already established QUIC connection. It returns an error if the QUIC connection didn't negotiate datagram support. The caller owns the QUIC connection and closes it when done. To reuse an existing HTTP/3 connection, use NewClientConn.

Directories

Path Synopsis
integration module

Jump to

Keyboard shortcuts

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