masktunnel

package module
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Feb 3, 2026 License: GPL-3.0 Imports: 37 Imported by: 1

README

GitHub Stars GitHub Actions Workflow Status Python Version PyPI - Version Go Version License

MaskTunnel

A smart proxy that automatically mimics different browsers to bypass detection systems.

中文文档 / Chinese README

What is MaskTunnel?

MaskTunnel is an HTTP proxy that automatically changes its "fingerprint" to match different browsers (Chrome, Firefox, Safari, etc.) based on the User-Agent header in requests. This helps bypass websites that try to detect and block automated traffic.

Key benefits:

  • JA3/JA4 TLS fingerprint simulation: Mimics real browser JA3/JA4 TLS fingerprints (Chrome, Firefox, Safari, Edge)
  • Akamai HTTP/2 fingerprint bypass: Replicates browser-specific HTTP/2 SETTINGS and frame patterns
  • Dynamic adaptation: Automatically selects correct fingerprints based on User-Agent headers
  • JavaScript injection: Inject custom code to bypass client-side detection
  • Zero configuration: Works out-of-the-box with any HTTP client or browser
  • Supports streaming: Support chunked and websocket connections

Installation

# Run with default settings
docker run -p 8080:8080 jackzzs/masktunnel
Binary Releases

Download pre-built binaries from the releases page.

Python Version
pip install masktunnel

The Python version is a wrapper of the Go implementation. See Python Bindings for usage.

Build from Source
go run github.com/cloudflyer-project/masktunnel/cmd/masktunnel

Usage

Start the Proxy

Basic proxy on port 8080:

./masktunnel -port 8080

Configure your browser or application to use http://localhost:8080 as the HTTP proxy.

Common Options

Add authentication:

./masktunnel -username myuser -password mypass -port 8080

Inject custom JavaScript into web pages:

./masktunnel -payload "console.log('Hello from MaskTunnel!');" -port 8080

Chain through another proxy:

./masktunnel -upstream-proxy http://upstream:8080 -port 8080
Testing the Fingerprinting

Test that different User-Agents produce different fingerprints:

Chrome fingerprint:

curl -k -x http://localhost:8080 \
     -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" \
     https://tls.peet.ws/api/all

Firefox fingerprint:

curl -k -x http://localhost:8080 \
     -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0" \
     https://tls.peet.ws/api/all

The fingerprints returned should be different for each browser.

Note: The -k flag disables SSL certificate verification. For production use, see Trusting the Certificate below.

Command Line Options

Option Description Default
-port Proxy listen port 8080
-addr Proxy listen address
-username Username for proxy authentication
-password Password for proxy authentication
-payload JavaScript to inject into responses
-upstream-proxy Forward requests to upstream proxy
-user-agent Override User-Agent header
-cert TLS certificate file cert.pem
-key TLS key file key.pem
-verbose Enable verbose logging 0

Internal Control API

MaskTunnel does not start a separate API server. Instead, it exposes internal control endpoints through the proxy server itself (default port 8080).

Reset TLS Sessions

Reset all active TLS sessions:

curl -X POST http://localhost:8080/__masktunnel__/reset

Response:

{"success":true,"closed_sessions":5}
Set Upstream Proxy

Dynamically change the upstream proxy at runtime:

curl -X POST http://localhost:8080/__masktunnel__/proxy \
     -d "http://new-upstream:8080"

Response:

{"success":true,"proxy":"http://new-upstream:8080","closed_sessions":3}

To remove the upstream proxy, send an empty body:

curl -X POST http://localhost:8080/__masktunnel__/proxy -d ""

Trusting the Certificate

MaskTunnel acts as a MITM (Man-in-the-Middle) proxy to intercept and modify HTTPS traffic. By default, it generates a self-signed certificate that browsers and tools will not trust, requiring the -k flag in curl or similar options in other clients.

To avoid certificate warnings and use MaskTunnel without -k, you can add the generated certificate to your system's trusted certificate store.

Certificate Location

The certificate file is located at:

  • Default: cert.pem in the working directory
  • Custom: Specified via -cert flag
Windows
  1. Double-click the cert.pem file, or rename it to cert.crt and double-click
  2. Click Install Certificate...
  3. Select Local Machine (requires admin) or Current User
  4. Choose Place all certificates in the following store
  5. Click Browse and select Trusted Root Certification Authorities
  6. Click Next and then Finish

Alternatively, using PowerShell (as Administrator):

Import-Certificate -FilePath "cert.pem" -CertStoreLocation Cert:\LocalMachine\Root
macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain cert.pem

Or via Keychain Access:

  1. Open Keychain Access (Applications → Utilities)
  2. Drag cert.pem into the System keychain
  3. Double-click the imported certificate
  4. Expand Trust and set When using this certificate to Always Trust
  5. Close the window and enter your password to confirm
Linux

Debian/Ubuntu:

sudo cp cert.pem /usr/local/share/ca-certificates/masktunnel.crt
sudo update-ca-certificates

RHEL/CentOS/Fedora:

sudo cp cert.pem /etc/pki/ca-trust/source/anchors/masktunnel.pem
sudo update-ca-trust

Arch Linux:

sudo cp cert.pem /etc/ca-certificates/trust-source/anchors/masktunnel.crt
sudo trust extract-compat
Browser-Specific Trust

Some browsers maintain their own certificate stores:

Firefox: Go to Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import

Chrome (Linux): Chrome uses the system store on most platforms, but on Linux you may need:

certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "MaskTunnel" -i cert.pem

Python Bindings

MaskTunnel provides Python bindings for easy integration into Python applications.

Installation
pip install masktunnel
Basic Usage
from masktunnel import Server

# Create and start a proxy server
server = Server()
print(f"Proxy running at: {server.addr}")

# Get the CA certificate for HTTPS interception
ca_pem = server.get_ca_pem()

# Stop the server when done
server.stop()
Async Usage
import asyncio
from masktunnel import Server

async def main():
    server = Server()
    print(f"Proxy running at: {server.addr}")
    
    # Run the server in background
    await server.async_start()
    
    # Do other async work...
    await asyncio.sleep(10)
    
    # Stop the server
    await server.async_stop()

asyncio.run(main())
Server Options
from masktunnel import Server
from masktunnel._server import ServerOptions

options = ServerOptions(
    port="9090",
    username="user",
    password="pass",
    payload="console.log('injected');",
    upstream_proxy="http://upstream:8080",
    verbose=1
)

server = Server(options=options)

Acknowledgments

MaskTunnel builds upon the excellent work of:

License

This project is licensed under the GPLv3 License.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Nanosecond  = time.Nanosecond
	Microsecond = time.Microsecond
	Millisecond = time.Millisecond
	Second      = time.Second
	Minute      = time.Minute
	Hour        = time.Hour
)
View Source
var (
	LevelTrace = zerolog.TraceLevel
	LevelDebug = zerolog.DebugLevel
	LevelInfo  = zerolog.InfoLevel
	LevelWarn  = zerolog.WarnLevel
	LevelError = zerolog.ErrorLevel
	LevelFatal = zerolog.FatalLevel
	LevelPanic = zerolog.PanicLevel
)

Zerolog level constants for Python bindings

View Source
var (
	Version  = "v1.1.2"
	Platform = runtime.GOOS + "/" + runtime.GOARCH
)

Functions

func Background added in v1.0.8

func Background() context.Context

Background returns a process-wide background context.

func CancelGlobalContext added in v1.0.8

func CancelGlobalContext()

CancelGlobalContext cancels the global background context.

func CancelLogWaiters added in v1.0.10

func CancelLogWaiters()

CancelLogWaiters cancels all waiting log listeners

func GetBrowserFingerprintJSON added in v1.0.8

func GetBrowserFingerprintJSON(userAgent string) (string, error)

GetBrowserFingerprintJSON returns a JSON string describing the fingerprint.

func GetSupportedBrowsers

func GetSupportedBrowsers() []string

GetSupportedBrowsers returns list of supported browsers

func GetSupportedBrowsersForPython added in v1.0.8

func GetSupportedBrowsersForPython() []string

GetSupportedBrowsersForPython returns the list of supported browser names.

func GetSupportedVersions

func GetSupportedVersions(browserName string) []int

GetSupportedVersions returns list of supported versions for specified browser

func GetSupportedVersionsForPython added in v1.0.8

func GetSupportedVersionsForPython(browserName string) []int

GetSupportedVersionsForPython returns the supported major versions for a browser.

func NewContext added in v1.0.8

func NewContext() context.Context

NewContext returns a new background-derived context.

func NewLogger added in v1.0.10

func NewLogger(cb func(line string)) zerolog.Logger

NewLogger creates a new zerolog.Logger with auto-generated ID

func NewLoggerWithID added in v1.0.10

func NewLoggerWithID(id string) zerolog.Logger

NewLoggerWithID creates a new zerolog.Logger that tags output with the given ID

func NewLoggerWithIDAndLevel added in v1.0.10

func NewLoggerWithIDAndLevel(id string, level zerolog.Level) zerolog.Logger

NewLoggerWithIDAndLevel creates a new zerolog.Logger with specified level that tags output with the given ID

func NewLoggerWithLevel added in v1.0.10

func NewLoggerWithLevel(level zerolog.Level, cb func(line string)) zerolog.Logger

NewLoggerWithLevel creates a new zerolog.Logger with auto-generated ID and specified level

func ParseDuration added in v1.0.8

func ParseDuration(s string) (time.Duration, error)

ParseDuration parses a duration string (e.g. "300ms", "2h45m").

func SetLoggerGlobalLevel added in v1.0.10

func SetLoggerGlobalLevel(level zerolog.Level)

SetLoggerGlobalLevel sets the global log level for all loggers

Types

type BasicAuth

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

BasicAuth handles HTTP Basic Authentication for proxy

func NewBasicAuth

func NewBasicAuth(username, password string) *BasicAuth

NewBasicAuth creates a new basic auth handler

func (*BasicAuth) GetAuthRequiredResponse

func (ba *BasicAuth) GetAuthRequiredResponse() *http.Response

GetAuthRequiredResponse returns HTTP 407 response for auth required

func (*BasicAuth) IsEnabled

func (ba *BasicAuth) IsEnabled() bool

IsEnabled returns true if authentication is enabled

func (*BasicAuth) Validate

func (ba *BasicAuth) Validate(req *http.Request) bool

Validate validates the proxy authentication from request

type BrowserFingerprint

type BrowserFingerprint struct {
	Browser          string
	HTTP2Fingerprint string
	TLSProfile       string
}

BrowserFingerprint contains complete browser fingerprint

func GetBrowserFingerprint

func GetBrowserFingerprint(userAgent string) (*BrowserFingerprint, error)

GetBrowserFingerprint gets complete browser fingerprint from User-Agent

type BrowserInfo

type BrowserInfo struct {
	Name    string
	Version string
	Major   int
}

BrowserInfo contains browser information

func ParseUserAgent

func ParseUserAgent(userAgent string) (*BrowserInfo, error)

ParseUserAgent parses User-Agent string

type BufferedMITMConn added in v1.0.6

type BufferedMITMConn struct {
	net.Conn
	Reader *bufio.Reader
}

BufferedMITMConn wraps a connection with a buffered reader for protocol detection

func (*BufferedMITMConn) Read added in v1.0.6

func (bc *BufferedMITMConn) Read(p []byte) (int, error)

type CertManager

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

CertManager manages certificate generation for MITM

func NewCertManager

func NewCertManager() (*CertManager, error)

NewCertManager creates a new certificate manager

func NewCertManagerFromFiles added in v1.0.17

func NewCertManagerFromFiles(certFile, keyFile string) (*CertManager, error)

NewCertManagerFromFiles creates a certificate manager and loads the CA certificate/key from disk when possible. If files are missing, it generates a new CA and persists it to the provided paths.

func (*CertManager) GetCACert

func (cm *CertManager) GetCACert() []byte

GetCACert returns the DER-encoded CA certificate bytes.

func (*CertManager) GetCACertDER added in v1.0.8

func (cm *CertManager) GetCACertDER() []byte

GetCACertDER returns the DER-encoded CA certificate bytes.

func (*CertManager) GetCACertPEM added in v1.0.8

func (cm *CertManager) GetCACertPEM() []byte

GetCACertPEM returns the PEM-encoded CA certificate.

func (*CertManager) GetCertificate

func (cm *CertManager) GetCertificate(hostname string) (*tls.Certificate, error)

GetCertificate returns a certificate for the given hostname

type ChunkedWriter added in v1.0.6

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

ChunkedWriter is a helper to wrap a net.Conn to write in chunked encoding format.

func NewChunkedWriter added in v1.0.6

func NewChunkedWriter(conn net.Conn, useChunked bool) *ChunkedWriter

NewChunkedWriter creates a new ChunkedWriter.

func (*ChunkedWriter) Close added in v1.0.6

func (cw *ChunkedWriter) Close() error

Close finalizes the stream. For chunked encoding, it writes the final zero-length chunk. This is implicitly called by io.Copy when the source reader returns EOF.

func (*ChunkedWriter) Write added in v1.0.6

func (cw *ChunkedWriter) Write(p []byte) (n int, err error)

Write implements io.Writer. It writes data in chunked format if useChunked is true.

type Config

type Config struct {
	Addr          string
	Port          string
	UserAgent     string
	Payload       string
	UpstreamProxy string
	Username      string
	Password      string
	CertFile      string
	KeyFile       string
	Verbose       int
	Logger        *zerolog.Logger // Custom logger for Python bindings
}

Config holds the proxy server configuration

type ContextWithCancel added in v1.0.8

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

ContextWithCancel wraps a context and its cancel function.

func NewContextWithCancel added in v1.0.8

func NewContextWithCancel() *ContextWithCancel

NewContextWithCancel creates a new cancellable context.

func (*ContextWithCancel) Cancel added in v1.0.8

func (c *ContextWithCancel) Cancel()

Cancel cancels the underlying context.

func (*ContextWithCancel) Context added in v1.0.8

func (c *ContextWithCancel) Context() context.Context

Context returns the underlying context.

type HTTP2Fingerprint

type HTTP2Fingerprint struct {
	Settings     string
	WindowUpdate string
	Priority     string
	PseudoHeader string
}

HTTP2Fingerprint contains HTTP/2 fingerprint configuration

type LogEntry added in v1.0.10

type LogEntry struct {
	LoggerID string
	Message  string
	Time     int64 // Unix timestamp in nanoseconds
}

LogEntry represents a single log entry with metadata

func GetLogEntries added in v1.0.10

func GetLogEntries() []LogEntry

GetLogEntries returns and clears log entries from the buffer

func WaitForLogEntries added in v1.0.10

func WaitForLogEntries(timeoutMs int64) []LogEntry

WaitForLogEntries waits for new log entries with timeout (in milliseconds) Returns log entries when available, or nil on timeout If timeoutMs is 0, waits indefinitely

type Manager

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

Manager manages all azuretls sessions

func NewManager

func NewManager() *Manager

NewManager creates a new session manager

func NewManagerWithLogger added in v1.0.10

func NewManagerWithLogger(logger zerolog.Logger) *Manager

NewManagerWithLogger creates a new session manager with custom logger

func (*Manager) CloseAll

func (m *Manager) CloseAll()

CloseAll closes all sessions

func (*Manager) GetSession

func (m *Manager) GetSession(userAgent, upstreamProxy string) (*azuretls.Session, error)

GetSession gets or creates session based on configuration

func (*Manager) GetSessionCount

func (m *Manager) GetSessionCount() int

GetSessionCount returns current session count

type PayloadInjector

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

PayloadInjector handles JavaScript payload injection into responses

func NewPayloadInjector

func NewPayloadInjector(payload string) *PayloadInjector

NewPayloadInjector creates a new payload injector

func (*PayloadInjector) InjectIntoResponse

func (p *PayloadInjector) InjectIntoResponse(body []byte, contentType string) []byte

InjectIntoResponse injects payload into HTTP response based on content type

func (*PayloadInjector) PrependToBuffer

func (p *PayloadInjector) PrependToBuffer(buf *bytes.Buffer, contentType string)

PrependToBuffer prepends payload to buffer for streaming responses

func (*PayloadInjector) ShouldInject

func (p *PayloadInjector) ShouldInject(contentType string) bool

ShouldInject checks if payload should be injected based on content type

type Server

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

Server represents the MaskTunnel proxy server

func NewServer

func NewServer(config *Config) *Server

NewServer creates a new proxy server instance

func (*Server) ActualAddr added in v1.0.16

func (s *Server) ActualAddr() string

ActualAddr returns the actual listening address (host:port). This is useful when port 0 is specified to get the OS-assigned port.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler interface

func (*Server) Start

func (s *Server) Start() error

Start starts the proxy server

func (*Server) Stop

func (s *Server) Stop() error

Stop stops the proxy server

type ServerHandle added in v1.0.8

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

ServerHandle wraps *Server for Python. Note: gopy doesn't like interfaces or embedded complex fields; keep it simple.

func NewServerHandle added in v1.0.8

func NewServerHandle(opt *ServerOption) *ServerHandle

NewServerHandle creates a new server handle.

func (*ServerHandle) Addr added in v1.0.8

func (h *ServerHandle) Addr() string

Addr returns the effective listen address (host:port). If the server has started, returns the actual bound address. Otherwise, returns the configured address.

func (*ServerHandle) Close added in v1.0.8

func (h *ServerHandle) Close() error

Close is an alias of Stop.

func (*ServerHandle) GetCAPEM added in v1.0.8

func (h *ServerHandle) GetCAPEM() []byte

GetCAPEM returns the in-memory CA certificate in PEM format.

func (*ServerHandle) ResetSessions added in v1.0.8

func (h *ServerHandle) ResetSessions() int

ResetSessions closes all cached TLS sessions.

func (*ServerHandle) SetUpstreamProxy added in v1.0.8

func (h *ServerHandle) SetUpstreamProxy(proxyURL string) error

SetUpstreamProxy sets the upstream proxy and resets sessions.

func (*ServerHandle) Start added in v1.0.8

func (h *ServerHandle) Start() error

Start starts the proxy server (blocking).

func (*ServerHandle) StartBackground added in v1.0.16

func (h *ServerHandle) StartBackground() error

StartBackground starts the proxy server in a background goroutine. It waits until the server is ready to accept connections, then returns. The actual listening address can be retrieved via Addr() after this returns.

func (*ServerHandle) Stop added in v1.0.8

func (h *ServerHandle) Stop() error

Stop stops the proxy server.

type ServerOption added in v1.0.8

type ServerOption struct {
	Addr          string
	Port          string
	UserAgent     string
	Payload       string
	UpstreamProxy string
	Username      string
	Password      string
	Verbose       int
	// contains filtered or unexported fields
}

ServerOption describes server configuration for bindings. Keep fields as basic types to ensure gopy can map them.

func DefaultServerOption added in v1.0.8

func DefaultServerOption() *ServerOption

DefaultServerOption returns default options.

func (*ServerOption) WithLogger added in v1.0.10

func (opt *ServerOption) WithLogger(logger zerolog.Logger)

WithLogger sets a custom logger for the server.

Directories

Path Synopsis
_bindings
cmd
masktunnel command

Jump to

Keyboard shortcuts

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