connectip

package module
v0.0.0-...-3109324 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: MIT Imports: 27 Imported by: 0

README

Proxying IP over HTTP

PkgGoDev Code Coverage

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-06, 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 AssignedAddress

type AssignedAddress struct {
	RequestID uint64
	IPPrefix  netip.Prefix
}

AssignedAddress represents an Assigned Address within an ADDRESS_ASSIGN capsule

type ClientConn

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 (*ClientConn) Dial

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. It returns once the assignment has been queued.

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) LocalPrefixes

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

LocalPrefixes returns the prefixes that the peer currently assigned. Note that at any point during the connection, the peer can change the assignment. It is therefore recommended to call this function in a loop.

func (*Conn) ReadPacket

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

func (*Conn) ReadPacketBuffer

func (c *Conn) ReadPacketBuffer() (*PacketBuffer, error)

ReadPacketBuffer receives one validated IP packet without copying its backing buffer. The caller must release the returned buffer.

func (*Conn) ReceiveDNSConfiguration

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

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) 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

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

SendDNSConfiguration schedules a DNS configuration update to the peer. It returns once the update has been queued. 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

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) TryReadPacketBuffer

func (c *Conn) TryReadPacketBuffer() (*PacketBuffer, error)

TryReadPacketBuffer drains one already queued datagram without waiting.

func (*Conn) WritePacket

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

WritePacket writes an IP packet to the stream. 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.

func (*Conn) WritePacketBuffer

func (c *Conn) WritePacketBuffer(buf []byte, offset, length int) ([]byte, error)

WritePacketBuffer sends an IP packet from a caller-provided buffer with room for the CONNECT-IP context ID immediately before offset.

func (*Conn) WritePacketBufferOwned

func (c *Conn) WritePacketBufferOwned(buf []byte, offset, length int, owner PacketPayloadOwner) (icmp []byte, err error)

WritePacketBufferOwned transfers ownership only when the lower layer accepts the owned send. All rejected or synchronous fallback paths release it.

type DNSConfiguration

type DNSConfiguration struct {
	Nameservers []DNSNameserver
	// InternalDomains contains fully qualified domain names in DNS presentation
	// format using IDNA A-labels. U-labels are rejected. An empty string
	// represents the DNS root.
	InternalDomains []string
	// SearchDomains contains fully qualified domain names in DNS presentation
	// format using IDNA A-labels. U-labels and empty strings are rejected.
	SearchDomains []string
}

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

type DNSNameserver

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. It must be in DNS presentation format using IDNA A-labels;
	// U-labels are rejected. 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 PacketBuffer

type PacketBuffer quic.DatagramBuffer

PacketBuffer is a zero-copy view over a QUIC datagram buffer.

func (*PacketBuffer) Release

func (b *PacketBuffer) Release()

type PacketPayloadOwner

type PacketPayloadOwner interface{ Release() }

PacketPayloadOwner owns the backing storage passed to WritePacketBufferOwned.

type Proxy

type Proxy struct{}

func (*Proxy) Proxy

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

type ProxyRequest

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

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

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

func (e *ProxyRequestParseError) Error() string

func (*ProxyRequestParseError) Unwrap

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

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

NewRequest creates a CONNECT-IP request.

func (*Request) Header

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 RequestedAddress

type RequestedAddress struct {
	RequestID uint64
	IPPrefix  netip.Prefix
}

RequestedAddress represents an Requested Address within an ADDRESS_REQUEST capsule

type Transport

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

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 NewClientConn.

func (*Transport) NewClientConn

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.

Jump to

Keyboard shortcuts

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