English | 简体中文
HTTPSeal is a Linux command-line tool for intercepting and logging HTTP and HTTPS traffic from a command that it launches. It uses Linux namespaces, DNS redirection, a local proxy, and a generated certificate authority to keep the interception scoped to the target process instead of changing system-wide proxy or trust settings.
Any credentials shown in the demo have been removed and invalidated.
- Linux with user namespace support enabled. User namespaces are available on Linux 3.8 and later, but some distributions or hardened systems disable them.
CAP_NET_BIND_SERVICEon thehttpsealbinary when using the default privileged ports 443 and 80.uidmap(newuidmapandnewgidmap) is recommended. HTTPSeal can fall back without it, but the target process may appear as UID/GID 0 inside the namespace.
HTTPSeal does not require installing its CA into the system trust store. It prepares an isolated CA bundle for the launched process.
git clone https://github.com/hmgle/httpseal.git
cd httpseal
make build
sudo make installmake install copies the binary to /usr/local/bin/httpseal and sets cap_net_bind_service.
go build -o httpseal ./cmd/httpseal
sudo cp httpseal /usr/local/bin/
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/httpsealIf you install the binary somewhere else, set the capability on that path.
Use -- to separate HTTPSeal flags from the command to run.
# Intercept HTTPS traffic.
httpseal -- curl https://api.github.com/users/octocat
# Show more request and response detail.
httpseal -v -- curl https://httpbin.org/get
# Include response bodies, including binary bodies, in log output.
httpseal -vv -- curl https://httpbin.org/get
# Intercept plain HTTP traffic as well as HTTPS.
httpseal --enable-http -- curl http://httpbin.org/get
# Write structured traffic logs.
httpseal -o traffic.json --format json -- curl https://httpbin.org/get
httpseal -o traffic.har --format har -- curl https://api.github.com/users/octocat
# Filter logged traffic.
httpseal --filter-host-suffix github.com --filter-method GET --log-body-limit 2048 -- curl https://api.github.com/users/octocat
# Mirror intercepted traffic as local HTTP for Wireshark.
httpseal --enable-mirror -- curl https://api.github.com/users/octocat
# Send upstream connections through SOCKS5.
httpseal --socks5-addr 127.0.0.1:1080 -- curl https://www.google.com
# Load settings from a config file. Explicit CLI flags override file values.
httpseal --config ./config.json --log-level minimal -- curl https://httpbin.org/get- HTTPSeal starts local DNS, HTTPS proxy, and optionally HTTP proxy and mirror servers.
- The target command runs in a new namespace.
- Inside that namespace, HTTPSeal bind-mounts generated resolver, hosts, NSS, and CA bundle files over the standard system paths.
- DNS lookups from the target command resolve through HTTPSeal's DNS server.
- Domains are mapped to loopback addresses, and connections on port 443 or optional port 80 reach HTTPSeal's local proxy.
- HTTPS connections receive dynamically generated certificates signed by HTTPSeal's CA. The target process trusts this CA through the isolated CA bundle.
- HTTPSeal forwards requests to the real upstream server, logs the exchange, and returns the upstream response to the target process.
By default, HTTPS interception is enabled and plain HTTP interception is disabled. Use --enable-http to intercept plain HTTP on port 80.
Unless --config is set, HTTPSeal reads one default JSON configuration path. The path is computed from the environment:
$XDG_CONFIG_HOME/httpseal/config.json # when XDG_CONFIG_HOME is set
~/.config/httpseal/config.json # otherwise, when HOME is available
./.httpseal/config.json # final fallbackYou can also pass a file explicitly:
httpseal --config ./config.json -- curl https://httpbin.org/getExplicitly changed CLI flags take precedence over values from the configuration file.
{
"verbose": false,
"extra_verbose": false,
"dns_ip": "127.0.53.1",
"dns_port": 53,
"upstream_dns": "8.8.8.8:53",
"proxy_port": 443,
"ca_dir": "",
"keep_ca": false,
"enable_http": true,
"http_port": 80,
"connection_timeout": 30,
"socks5_enabled": false,
"socks5_address": "127.0.0.1:1080",
"socks5_username": "",
"socks5_password": "",
"upstream_ca_file": "",
"upstream_client_cert": "",
"upstream_client_key": "",
"upstream_server_name": "",
"upstream_insecure_skip_verify": false,
"output_file": "",
"output_format": "text",
"log_level": "normal",
"file_log_level": "",
"log_file": "",
"quiet": false,
"no_redact": false,
"capture_body_limit": 1048576,
"log_body_limit": 0,
"filter_domains": [],
"filter_host_exact": [],
"filter_host_suffix": [],
"filter_methods": [],
"filter_status_codes": [],
"filter_paths": [],
"exclude_content_types": ["image/", "video/", "audio/"],
"decompress_response": true,
"enable_mirror": false,
"mirror_port": 8080
}If ca_dir or --ca-dir is not set, HTTPSeal uses:
$XDG_CONFIG_HOME/httpseal/ca
~/.config/httpseal/caThe default CA directory is persistent. Generated CA and domain certificates are reused across runs. If the default directory cannot be created, HTTPSeal falls back to a temporary CA directory and removes it on exit unless --keep-ca is set.
HTTPSeal supports text, json, csv, and har output:
httpseal -o traffic.txt --format text -- curl https://httpbin.org/get
httpseal -o traffic.json --format json -- curl https://httpbin.org/get
httpseal -o traffic.csv --format csv -- curl https://httpbin.org/get
httpseal -o traffic.har --format har -- curl https://httpbin.org/getConsole and file logging levels can be set separately:
httpseal --log-level minimal --file-log-level verbose -o traffic.log -- curl https://httpbin.org/get
httpseal -q -o traffic.json --format json -- curl https://httpbin.org/get
httpseal --log-file system.log -o traffic.har --format har -- curl https://httpbin.org/getLogging levels are none, minimal, normal, verbose, and extra-verbose. -v enables verbose mode, and -vv enables extra-verbose mode. When -o is used and --file-log-level is not set, file logging defaults to verbose. Quiet mode (-q) requires an output file.
Important logging semantics:
duration_msis emitted in JSON, CSV, and HAR output.- JSON request and response headers preserve repeated header values as arrays.
--filter-domain,--filter-host-exact,--filter-host-suffix,--filter-method,--filter-status, and--filter-pathcombine with AND semantics.--capture-body-limitcontrols how many bytes are captured per request or response. Larger bodies spill to a temporary file while the configured prefix is retained for logs.--log-body-limitcontrols how many captured body bytes are written to console, text, CSV, JSON, and HAR output.--max-body-sizeremains as a deprecated alias.- Sensitive headers, URL query parameters, and text bodies are redacted by default. Use
--no-redactto disable redaction. - Compressed response bodies are decompressed for logging by default. Use
--decompress-response=falseto keep compressed bodies as-is in logs.
--enable-mirror starts a local HTTP mirror server on 127.0.0.1:8080 by default. HTTPSeal sends a second, plain HTTP representation of each intercepted exchange to this port so tools such as Wireshark can inspect the request and response without TLS decryption setup.
# Terminal 1
wireshark -i lo -f "tcp port 8080"
# Terminal 2
httpseal --enable-mirror -- curl https://api.github.com/users/octocatUse a different mirror port when needed:
httpseal --enable-mirror --mirror-port 9090 -- curl https://httpbin.org/getMirror traffic includes trace headers such as X-HTTPSeal-Original-Host, X-HTTPSeal-Mirror-ID, and X-HTTPSeal-Timestamp. The mirror path uses the original request and response bodies before log redaction and log body trimming, so treat mirror captures as sensitive.
SOCKS5 applies to upstream connections from HTTPSeal to the real server. The target application does not need proxy settings.
# Use the default SOCKS5 address, 127.0.0.1:1080.
httpseal --socks5 -- curl https://www.google.com
# Setting any SOCKS5 parameter also enables SOCKS5 mode.
httpseal --socks5-addr 127.0.0.1:1080 -- curl https://www.google.com
# Username/password authentication.
httpseal --socks5-addr 127.0.0.1:1080 --socks5-user user --socks5-pass pass -- curl https://api.github.comUpstream TLS options configure how HTTPSeal verifies and authenticates to the real server:
httpseal \
--upstream-ca-file ./certs/upstream-ca.pem \
--upstream-client-cert ./certs/client.pem \
--upstream-client-key ./certs/client-key.pem \
-- curl https://internal.example.test--upstream-server-name globally overrides SNI and hostname verification for every upstream TLS connection. Use it only when all intercepted TLS traffic is expected to match the same certificate name. --upstream-insecure-skip-verify disables upstream certificate verification and should be limited to controlled test environments.
httpseal [flags] -- <command> [args...]
Network:
--dns-ip string DNS server IP address (default "127.0.53.1")
--dns-port int DNS server port (default 53)
--upstream-dns string Upstream DNS server used for forwarded non-hijacked queries (default "8.8.8.8:53")
--proxy-port int HTTPS proxy port (default 443)
--connection-timeout int Client connection idle timeout in seconds (default 30)
Certificate management:
--ca-dir string Certificate authority directory (default: XDG_CONFIG_HOME/httpseal/ca)
--keep-ca Keep CA directory after exit (always true for default persistent directory)
HTTP interception:
--enable-http Enable HTTP traffic interception (default: disabled)
--http-port int HTTP proxy port (default 80)
SOCKS5 and upstream TLS:
--socks5 Enable SOCKS5 proxy with default address (127.0.0.1:1080)
--socks5-addr string SOCKS5 proxy address (auto-enables SOCKS5 when specified) (default "127.0.0.1:1080")
--socks5-user string SOCKS5 username for authentication (optional)
--socks5-pass string SOCKS5 password for authentication (optional)
--upstream-ca-file string Additional CA bundle used to verify upstream TLS certificates
--upstream-client-cert string Client certificate PEM used for upstream mTLS
--upstream-client-key string Client private key PEM used for upstream mTLS
--upstream-server-name string Globally override the upstream TLS server name for all upstream TLS connections
--upstream-insecure-skip-verify Skip upstream TLS certificate verification
Wireshark mirror:
--enable-mirror Enable HTTP mirror server for Wireshark analysis
--mirror-port int HTTP mirror server port for Wireshark capture (default 8080)
Output:
-o, --output string Output traffic to file
--format string Output format: text, json, csv, har (default "text")
--log-level string Console logging level: none, minimal, normal, verbose, extra-verbose (default "normal")
--file-log-level string File logging level (defaults to verbose when -o is used): none, minimal, normal, verbose, extra-verbose
--log-file string Output system logs to file (separate from traffic data)
-q, --quiet Suppress console output
-v, --verbose count Enable verbose output (-v for verbose, -vv for extra-verbose)
--no-redact Disable default redaction of sensitive headers, URLs, and text bodies
Filtering and body handling:
--filter-domain strings Only log traffic for these domains (can be repeated)
--filter-host-exact strings Only log traffic for these exact hosts
--filter-host-suffix strings Only log traffic for hosts matching these suffixes
--filter-method strings Only log traffic for these HTTP methods
--filter-status ints Only log traffic for these HTTP status codes
--filter-path strings Only log traffic whose request path contains one of these strings
--exclude-content-type strings Exclude these content types from logging
--capture-body-limit int Maximum request/response body bytes to capture per message (0=unlimited) (default 1048576)
--log-body-limit int Maximum captured body bytes to print/write (0=full captured body)
--max-body-size int Deprecated alias for --log-body-limit
--decompress-response Decompress compressed response bodies for logging (default true)
Configuration and metadata:
-c, --config string Configuration file path (default: XDG_CONFIG_HOME/httpseal/config.json)
-h, --help Show help
--version Show version
The default HTTPS and HTTP interception ports are 443 and 80. If HTTPSeal cannot bind those ports, set the required capability:
sudo setcap 'cap_net_bind_service=+ep' "$(command -v httpseal)"You can also choose unprivileged ports with --proxy-port and --http-port, but transparent interception of normal HTTPS/HTTP traffic expects the standard ports.
Some systems do not install newuidmap and newgidmap by default. On Debian and Ubuntu, install them with:
sudo apt install uidmapIf these helpers are missing, HTTPSeal falls back to unshare --map-root-user. In that fallback mode, the process may appear as UID/GID 0 inside the namespace, while files created on the host still map to the invoking user.
HTTPSeal tries to drop from namespace root back to the invoking user with setpriv, and then runuser when available. Some systems reject this. If privilege dropping fails, HTTPSeal continues as namespace root. Use -v or -vv to show the fallback details.
Archive tools such as tar, gtar, and bsdtar may try to restore UID/GID values that are not mapped inside the namespace. HTTPSeal detects these commands and sets:
TAR_OPTIONS=--no-same-owner --no-same-permissionsSet TAR_OPTIONS yourself before running HTTPSeal if you need different behavior.
Common causes:
- The target application uses hard-coded IP addresses instead of DNS.
- The target application uses a custom resolver or ignores
/etc/resolv.conf. - The target application does not use the CA locations or environment variables prepared by HTTPSeal.
- Another local service is already bound to port 443, or to port 80 when
--enable-httpis used. - The target protocol is not HTTP over TLS or plain HTTP.
Project layout:
cmd/httpseal/ CLI entry point
internal/config/ Configuration loading and merge logic
pkg/cert/ CA and dynamic certificate generation
pkg/dns/ DNS server and domain-to-loopback mapping
pkg/logger/ Traffic records, redaction, output formats
pkg/mirror/ Local HTTP mirror server
pkg/mount/ Mount helpers
pkg/namespace/ Namespace wrapper and bind mounts
pkg/proxy/ HTTPS and HTTP interception proxy
Common commands:
make build
make test
make fmt
make vet
make lint
make dev
make cleanHTTPSeal performs man-in-the-middle interception for the process it launches. Use it only for development, debugging, and authorized security testing.
HTTPSeal is designed to avoid system-wide trust or proxy changes, but captured traffic can include credentials, tokens, cookies, and request or response bodies. Store logs and mirror captures accordingly. Do not use HTTPSeal for production monitoring or for traffic you are not authorized to inspect.
- Fork the repository.
- Create a feature branch.
- Run the relevant checks.
- Open a pull request with a concise description of the change.
This project is licensed under the MIT License. See LICENSE for details.