camouflage

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: AGPL-3.0, AGPL-3.0-or-later Imports: 27 Imported by: 0

README

libp2p-camouflage-transport

Package provides a libp2p transport wrapper that defeats Deep Packet Inspection through two complementary techniques:

  1. TLS camouflage – a real TLS tunnel is established using uTLS with a genuine browser fingerprint (Chrome, Firefox, etc.) on the client side and standard crypto/tls with a plausible certificate chain on the server side. The Noise protocol handshake and all application data travel inside this TLS tunnel, making the connection indistinguishable from normal HTTPS browser traffic to DPI middleboxes.

  2. TCP fragmentation – the initial bytes of the TLS ClientHello are split into small TCP segments with random inter-segment delays so that stateful DPI that only inspects the first segment cannot match known signatures.

Active probing defenses include SNI/ALPN consistency validation, a plausible two-certificate chain (fake CA + leaf), and configurable handshake timeouts.

Documentation

Index

Constants

View Source
const (
	// DefaultFragmentSize is the number of bytes per TCP segment during
	// the handshake phase. Small values (1-3) are most effective at defeating
	// DPI signature matching on the first segment.
	DefaultFragmentSize = 2

	// DefaultHandshakeLen is the number of initial bytes subject to
	// fragmentation. This covers the whole TLS ClientHello.
	DefaultHandshakeLen = 2048

	// DefaultMaxDelay is the upper bound for the random delay inserted
	// between handshake fragments. Zero disables the delay.
	DefaultMaxDelay = 0
)
View Source
const (
	BrowserChrome  = "chrome"
	BrowserFirefox = "firefox"
	BrowserSafari  = "safari"
	BrowserEdge    = "edge"
	BrowserIOS     = "ios"
	BrowserAndroid = "android"
	BrowserYandex  = "yandex"
)

Well-known browser fingerprint identifiers for WithBrowserFingerprint.

Variables

This section is empty.

Functions

This section is empty.

Types

type CamouflageConfig

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

CamouflageConfig holds the TLS camouflage settings shared by all connections created by a single SpoofTransport instance.

func BuildCamouflageConfig

func BuildCamouflageConfig(
	sni, browserFingerprint string,
	handshakeTimeout time.Duration,
) (*CamouflageConfig, error)

BuildCamouflageConfig constructs the CamouflageConfig from transport settings. Called once during construction.

type CamouflageConn

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

CamouflageConn wraps a TCP connection with a real TLS tunnel. The client side uses uTLS to present a genuine browser TLS fingerprint (Chrome, Firefox, etc.), while the server side uses standard crypto/tls with a plausible certificate chain. All traffic inside the tunnel is indistinguishable from normal HTTPS browsing to DPI middleboxes.

func NewCamouflageConn

func NewCamouflageConn(conn manet.Conn, isClient bool, cfg *CamouflageConfig) (*CamouflageConn, error)

NewCamouflageConn wraps conn with a real TLS tunnel and performs the TLS handshake. isClient determines whether this side initiates the handshake (uTLS with browser fingerprint) or accepts (crypto/tls server).

func (*CamouflageConn) Close

func (cc *CamouflageConn) Close() error

func (*CamouflageConn) CloseRead

func (cc *CamouflageConn) CloseRead() error

CloseRead forwards to the underlying connection if supported.

func (*CamouflageConn) CloseWrite

func (cc *CamouflageConn) CloseWrite() error

CloseWrite sends a TLS close_notify alert if the underlying TLS connection supports half-close.

func (*CamouflageConn) LocalAddr

func (cc *CamouflageConn) LocalAddr() net.Addr

func (*CamouflageConn) LocalMultiaddr

func (cc *CamouflageConn) LocalMultiaddr() ma.Multiaddr

func (*CamouflageConn) Read

func (cc *CamouflageConn) Read(b []byte) (int, error)

func (*CamouflageConn) RemoteAddr

func (cc *CamouflageConn) RemoteAddr() net.Addr

func (*CamouflageConn) RemoteMultiaddr

func (cc *CamouflageConn) RemoteMultiaddr() ma.Multiaddr

func (*CamouflageConn) SetDeadline

func (cc *CamouflageConn) SetDeadline(t time.Time) error

func (*CamouflageConn) SetReadDeadline

func (cc *CamouflageConn) SetReadDeadline(t time.Time) error

func (*CamouflageConn) SetWriteDeadline

func (cc *CamouflageConn) SetWriteDeadline(t time.Time) error

func (*CamouflageConn) Write

func (cc *CamouflageConn) Write(b []byte) (int, error)

type CamouflageTransport

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

CamouflageTransport is a libp2p transport that wraps TCP connections with real TLS camouflage (uTLS browser fingerprint) and handshake-phase traffic fragmentation to evade DPI.

func NewCamouflageTransport

func NewCamouflageTransport(
	upgrader transport.Upgrader,
	rcmgr network.ResourceManager,
	sharedTCP *tcpreuse.ConnMgr,
	opts ...Option,
) (*CamouflageTransport, error)

NewCamouflageTransport creates a DPI-evasion transport. The constructor signature is compatible with libp2p.Transport() dependency injection: the framework injects the upgrader, resource manager, and shared TCP manager automatically.

func (*CamouflageTransport) CanDial

func (t *CamouflageTransport) CanDial(addr ma.Multiaddr) bool

CanDial returns true if the transport can dial the given multiaddr.

func (*CamouflageTransport) Dial

Dial dials the remote peer, wrapping the raw TCP connection with SpoofConn + real TLS camouflage before the Noise handshake.

func (*CamouflageTransport) DialWithUpdates added in v0.0.2

func (t *CamouflageTransport) DialWithUpdates(
	ctx context.Context,
	raddr ma.Multiaddr,
	p peer.ID,
	updateChan chan<- transport.DialUpdate,
) (transport.CapableConn, error)

DialWithUpdates dials the remote peer and reports dial progress on updateChan.

func (*CamouflageTransport) Listen

func (*CamouflageTransport) Protocols

func (t *CamouflageTransport) Protocols() []int

Protocols returns the set of protocols handled by this transport.

func (*CamouflageTransport) Proxy

func (t *CamouflageTransport) Proxy() bool

Proxy always returns false.

func (*CamouflageTransport) String

func (t *CamouflageTransport) String() string

type Option

type Option func(*CamouflageTransport) error

func WithBrowserFingerprint

func WithBrowserFingerprint(browser string) Option

WithBrowserFingerprint selects which browser's TLS fingerprint to mimic. Use the Browser* constants (e.g. BrowserChrome, BrowserFirefox). Defaults to Chrome if empty or unknown.

func WithConnectTimeout

func WithConnectTimeout(d time.Duration) Option

WithConnectTimeout sets the TCP connect timeout. Non-positive values are ignored.

func WithFragmentSize

func WithFragmentSize(size int) Option

WithFragmentSize sets the number of bytes per TCP segment during the handshake phase.

func WithHandshakeLen

func WithHandshakeLen(n int) Option

WithHandshakeLen sets the total number of bytes subject to fragmentation.

func WithHandshakeTimeout

func WithHandshakeTimeout(d time.Duration) Option

WithHandshakeTimeout sets the maximum duration for the TLS handshake. Connections that do not complete the handshake within this window are closed, defending against slow-handshake active probing. Non-positive values are ignored.

func WithMaxDelay

func WithMaxDelay(d time.Duration) Option

WithMaxDelay sets the upper bound for random inter-fragment delays. Zero disables delays; negative values are ignored.

func WithSNI

func WithSNI(sni string) Option

WithSNI sets the Server Name Indication value used in the TLS ClientHello. Defaults to "www.googleapis.com".

type SpoofConn

type SpoofConn struct {
	manet.Conn
	// contains filtered or unexported fields
}

SpoofConn wraps a manet.Conn and splits Write calls during the handshake phase (the first handshakeLen bytes). After the handshake, writes pass through without modification.

func NewSpoofConn

func NewSpoofConn(conn manet.Conn, fragmentSize, handshakeLen int, maxDelay time.Duration, sni string) *SpoofConn

NewSpoofConn wraps conn. A non-empty sni switches to a single split inside the name instead of chunking the handshake prefix.

func (*SpoofConn) CloseRead

func (c *SpoofConn) CloseRead() error

CloseRead forwards to the underlying connection if supported.

func (*SpoofConn) CloseWrite

func (c *SpoofConn) CloseWrite() error

CloseWrite forwards to the underlying connection if supported.

func (*SpoofConn) Write

func (c *SpoofConn) Write(b []byte) (int, error)

Write fragments b into small segments if the handshake phase is still active; otherwise it delegates directly to the underlying connection.

Jump to

Keyboard shortcuts

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