- Go 97.7%
- Shell 2.1%
- Makefile 0.2%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| cmd/teleport | ||
| internal | ||
| pkg | ||
| scripts | ||
| .gitignore | ||
| .goreleaser.yaml | ||
| CONTRIBUTING.md | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
Teleport - Secure Port Forwarding
Teleport is a secure port forwarding tool that allows you to forward ports between different instances with end-to-end encryption.
How It Works
┌─────────────────┐ Encrypted Tunnel ┌─────────────────┐
│ Client A │◄────── Port 9000 ──────►│ Teleport │
│ │ │ Server │
│ │ │ │
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │teleport │ │ │ │teleport │ │
│ │client │ │ │ │server │ │
│ └───────────┘ │ │ └───────────┘ │───────────┐
└─────────────────┘ └─────────────────┘ │
│ │ │
│ Ports 8080,2222 │ Ports 80,22 │
│ (local) │ (targets) │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ User connects │ │ Remote │ │ Remote │
│ to localhost: │ │ Web Server │ │ SSH Server │
│ 8080, 2222 │ │ (192.168.1.100) │ │ (192.168.1.200) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Flow: User → Client:8080,2222 → Encrypted Tunnel (Port 9000) → Server:80,22 → Remote Services
Note: The different ports (8080/2222 vs 80/22) are shown for demonstration purposes only. Client and service ports can be identical - teleport will handle the port mapping transparently.
Example Configuration
Server Configuration (server.yaml):
instance_id: teleport-server-01
listen_address: 127.0.0.1:9000 # loopback; use 0.0.0.0:9000 to publish
remote_address: ""
ports:
- "tcp://192.168.1.100:80"
- "tcp://192.168.1.200:22"
encryption_key: your-secure-encryption-key-here
keep_alive: true
read_timeout: 30s
write_timeout: 30s
Client Configuration (client.yaml):
instance_id: teleport-client-01
listen_address: ""
remote_address: server.example.com:9000
bind_address: 127.0.0.1
ports:
- "tcp://80:8080"
- "tcp://22:2222"
encryption_key: your-secure-encryption-key-here
keep_alive: true
read_timeout: 30s
write_timeout: 30s
Usage:
- User connects to
127.0.0.1:8080(client local listener, loopback by default) → Traffic flows through encrypted tunnel on127.0.0.1:9000→ Server forwards to remote web server at192.168.1.100:80 - User connects to
127.0.0.1:2222→ Traffic flows through the same encrypted tunnel → Server forwards to remote SSH server at192.168.1.200:22
Local client ports bind 127.0.0.1 unless you set bind_address: 0.0.0.0 or a per-rule host such as "tcp://22:0.0.0.0:2222". Server listen_address: 127.0.0.1:9000 is loopback-only; 0.0.0.0:9000 (or :9000) publishes the tunnel on all interfaces and must be explicit.
Both services share the same encrypted tunnel connection!
Features
- Secure Encryption: All traffic is encrypted using AES-GCM. New keys are raw 256-bit AES keys; passphrase-style configs still use PBKDF2
- Port Forwarding: Forward multiple ports with different protocols (TCP and UDP)
- Configuration-based: Easy configuration via YAML files
- Bidirectional: Full bidirectional port forwarding
- Keep-alive: Connection keep-alive support
- Protocol Support: Both TCP and UDP protocols supported
- Multi-Client Support: Multiple clients can connect to one server using packet tagging
- UDP Packet Tagging: UDP packets are tagged with client IDs for proper routing
- Built-in DNS Server: Custom DNS server with configurable records and backup fallback
- Rate Limiting: Configurable rate limiting with token bucket algorithm
- Connection Pooling: Efficient connection management with pooling
- Replay Protection: UDP packet replay attack protection with timestamp validation
- Advanced Logging: Sanitized logging with configurable levels, formats, and file output
- Security Features: Entropy validation, packet timestamp validation, and secure key generation
Installation
# Build the application (runs the toolchain check first)
make build
# Or use the pre-built binaries from releases
# Windows: teleport.exe (no console) or teleport-console.exe (with console)
# Linux: teleport
make build first runs scripts/check-toolchain.sh: it checks that your Go matches the toolchain line in go.mod (same minor, patch at least the required one) and that go.mod's go/toolchain lines haven't been rewritten. On a mismatch it stops before building and prints what it found, what's required, and the exact fix (install the listed Go, or git checkout go.mod).
Configuration
Teleport uses YAML configuration files. You need separate configurations for server and client instances.
Generate Example Configuration
Generate example configuration files:
# Generate server configuration (filename contains "server")
./teleport --generate-config --config server.yaml
# Generate client configuration
./teleport --generate-config --config client.yaml
# Generate default configuration (client)
./teleport --generate-config
Server Configuration (server.yaml)
instance_id: teleport-server-01
listen_address: 127.0.0.1:8080 # use 0.0.0.0:8080 to accept remote clients
remote_address: ""
ports:
- "tcp://localhost:80"
encryption_key: your-secure-encryption-key-change-this-to-something-random
keep_alive: true
read_timeout: 30s
write_timeout: 30s
max_connections: 1000
rate_limit:
enabled: true
requests_per_second: 100
burst_size: 200
window_size: 1s
dns_server:
enabled: false
listen_port: 5353
backup_server: 8.8.8.8:53
custom_records: []
Client Configuration (client.yaml)
instance_id: teleport-client-01
listen_address: ""
remote_address: localhost:8080
bind_address: 127.0.0.1
ports:
- "tcp://80:8080"
encryption_key: your-secure-encryption-key-change-this-to-something-random
keep_alive: true
read_timeout: 30s
write_timeout: 30s
max_connections: 100
rate_limit:
enabled: true
requests_per_second: 50
burst_size: 100
window_size: 1s
dns_server:
enabled: false
listen_port: 5353
backup_server: 8.8.8.8:53
custom_records:
- name: app.local
type: A
value: 127.0.0.1
ttl: 300
Configuration Fields
instance_id: Unique identifier for this teleport instancelisten_address: Address the server binds for the encrypted tunnel (host:port). Examples use127.0.0.1:9000. Use0.0.0.0:9000or:9000only when you intend to publish the server on all interfaces.remote_address: Address of remote teleport server (client mode) - format:host:portbind_address: Host for client local TCP/UDP listeners (default:127.0.0.1). Set to0.0.0.0to accept connections from other machines. Publishing on all interfaces is never implicit.ports: Array of port forwarding rules in URL-style format- Server format:
protocol://target:targetport- forwards to remote target - Client format:
protocol://targetport:localport- forwards to teleport server's targetport, listens onbind_address:localport(default127.0.0.1) - Client with bind:
protocol://targetport:bindhost:localport- per-rule listen host, e.g."tcp://22:0.0.0.0:2222" - Examples:
"tcp://localhost:80"(server) - forward to localhost:80"tcp://server-a:22"(server) - forward to server-a:22"tcp://80:8080"(client) - listen on127.0.0.1:8080, forward to teleport server's port 80"tcp://22:0.0.0.0:2222"(client) - listen on all interfaces port 2222"udp://53:5353"(client) - listen on127.0.0.1:5353, forward to teleport server's port 53
- Server format:
encryption_key: Shared secret (must be the same on both sides). New keys from--generate-key/--generate-configareraw:plus 64 hex characters (32-byte AES-256 key, no PBKDF2). Unprefixed values — passphrases and hex strings from older--generate-key— still go through PBKDF2 so existing configs keep working. To migrate an old hex key to raw AES, re-generate with--generate-keyand update both sides together; do not stripraw:from a new key or addraw:to an old hex string.keep_alive: Enable TCP keep-alive on tunnel and forwarded TCP connections (helps long-lived forwards through NAT)read_timeout: Read timeout durationwrite_timeout: Write timeout durationmax_connections: Maximum concurrent connections (default: 1000 for server, 100 for client)rate_limit: Rate limiting configurationenabled: Enable rate limitingrequests_per_second: Maximum requests per secondburst_size: Maximum burst sizewindow_size: Time window for rate limiting
dns_server: DNS server configurationenabled: Enable built-in DNS serverlisten_port: Port for DNS server to listen onbind_address: DNS listen host (default:127.0.0.1). Set to0.0.0.0to serve DNS on all interfaces; the default is not an open recursive forwarder on every interface.backup_server: Backup DNS server for fallback (e.g., "8.8.8.8:53")custom_records: Array of custom DNS recordsname: Domain name (e.g., "example.com")type: Record type ("A", "AAAA", "CNAME", "MX", "TXT", "SRV", "NS")value: Record value (IP address, domain name, or text)ttl: Time to live in secondspriority: Priority for MX and SRV records (optional)weight: Weight for SRV records (optional)port: Port for SRV records (optional)
Quick Start
-
Generate a secure encryption key:
./teleport --generate-key -
Generate configuration files:
./teleport --generate-config --config server.yaml ./teleport --generate-config --config client.yaml -
Edit the configs and replace the encryption key with the one you generated
-
Start the server:
./teleport --config server.yaml -
Start the client:
./teleport --config client.yaml
Usage
Start Server
./teleport --config server.yaml
Start Client
./teleport --config client.yaml
Show Version
./teleport --version
# or
./teleport -v
Generate Random Encryption Key
./teleport --generate-key
# or
./teleport -k
This prints a raw: prefixed 256-bit key. Paste the entire value into encryption_key on both server and client. It is used as an AES-256 key directly (no PBKDF2). Existing configs that store a passphrase or an unprefixed hex string still use PBKDF2.
--generate-config writes the file mode 0600 because the file embeds a live encryption key.
Logging Options
# Set log level (debug, info, warn, error)
./teleport --config config.yaml --log-level debug
# Set log format (text, json)
./teleport --config config.yaml --log-format json
# Set log file
./teleport --config config.yaml --log-file /var/log/teleport.log
Port Format
Teleport uses URL-style port mapping format for cleaner configuration:
ports:
- "tcp://80:8080" # Listen on 127.0.0.1:8080, forward to teleport server's port 80
- "udp://53:5353" # Listen on 127.0.0.1:5353, forward to teleport server's port 53
- "tcp://22:0.0.0.0:2222" # Explicit all-interfaces bind
Format:
- Server:
"protocol://target:targetport"- forward to target:targetport - Client:
"protocol://targetport:localport"- listen on127.0.0.1:localport(orbind_address), forward to teleport server's targetport - Client with bind:
"protocol://targetport:bindhost:localport"- listen on bindhost:localport
Examples:
# Server configurations
ports:
- "tcp://localhost:80" # Listen on port 80, forward to localhost:80
- "tcp://server-a:22" # Listen on port 22, forward to server-a:22
- "udp://dns-server:53" # Listen on port 53, forward to dns-server:53
# Client configurations
ports:
- "tcp://80:8080" # Listen on 127.0.0.1:8080, forward to teleport server's port 80
- "tcp://22:2222" # Listen on 127.0.0.1:2222, forward to teleport server's port 22
- "tcp://22:0.0.0.0:2222" # Listen on all interfaces (explicit)
- "udp://53:5353" # Listen on 127.0.0.1:5353, forward to teleport server's port 53
Example: Remote SSH Access To access SSH on Server A through teleport server on Server B:
Server B configuration:
instance_id: teleport-server-b
listen_address: 127.0.0.1:8080
remote_address: ""
ports:
- "tcp://server-a:22" # Forward to server-a:22
encryption_key: your-shared-key
Client C configuration:
instance_id: teleport-client-c
listen_address: ""
remote_address: server-b:8080
bind_address: 127.0.0.1
ports:
- "tcp://22:2222" # Listen on 127.0.0.1:2222, forward to teleport server's port 22
encryption_key: your-shared-key
Then connect from Client C: ssh user@localhost -p 2222
Configuration-Based Mode Detection
The mode (server or client) is automatically determined from the configuration:
- Server Mode: When
listen_addressis set andremote_addressis empty - Client Mode: When
remote_addressis set andlisten_addressis empty
Important: The configuration must be clearly either a server or client - you cannot have both listen_address and remote_address set, and you must have at least one of them set.
Configuration Validation
The program validates your configuration and will show clear error messages if:
- Both addresses set: You have both
listen_addressandremote_addressconfigured - Neither address set: You have neither
listen_addressnorremote_addressconfigured
Valid Server Configuration:
listen_address: 127.0.0.1:8080
remote_address: ""
ports:
- "tcp://localhost:22"
Valid Client Configuration:
listen_address: ""
remote_address: server:8080
bind_address: 127.0.0.1
ports:
- "tcp://22:2222"
Security
- All traffic is encrypted using AES-GCM encryption with PBKDF2 key derivation
- The encryption key is derived from the provided key using PBKDF2 with 100,000 iterations
- Each connection uses a unique nonce for encryption
- Connection authentication is implicit through successful decryption
- UDP packets include replay protection with timestamp validation
- Encryption keys are validated for entropy and strength
- Logging includes automatic sanitization of sensitive data
- Rate limiting prevents abuse and DoS attacks
- Client local listeners and the built-in DNS server bind
127.0.0.1by default so LAN/internet hosts cannot use your tunnel unless you setbind_address/ a per-rule host to0.0.0.0
Example Use Cases
- SSH Tunneling: Forward SSH connections through a secure tunnel
- Database Access: Securely access remote databases
- Web Services: Forward HTTP/HTTPS traffic
- DNS Services: Forward DNS queries (UDP port 53)
- NTP Services: Forward time synchronization (UDP port 123)
- SNMP Monitoring: Forward SNMP queries (UDP port 161)
- Custom Services: Forward any TCP or UDP-based service
- Local DNS Resolution: Serve custom DNS records for local development
- DNS Override: Override specific domains with custom IP addresses
- Service Discovery: Use SRV records for service discovery and load balancing
Example Setup
-
Server Side (where services are running):
- Generate:
./teleport -generate-config -config teleport-server.yaml - Edit the configuration file with the services you want to expose
- Run:
./teleport -config teleport-server.yaml
- Generate:
-
Client Side (where you want to access services):
- Generate:
./teleport -generate-config -config teleport-client.yaml - Edit the configuration file with local ports and remote server address
- Run:
./teleport -config teleport-client.yaml - Connect to
127.0.0.1:local_port(loopback by default) to access the remote service
- Generate:
Multi-Client Support
Multiple clients can connect to the same server using packet tagging:
- Start Server:
./teleport -config teleport-server.yaml - Start Client 1:
./teleport -config teleport-client.yaml - Start Client 2:
./teleport -config teleport-client2.yaml
Both clients can use the same local ports (e.g., 5353 for DNS) because:
- Each client has a unique
instance_idin their config - UDP packets are tagged with the client ID
- Server routes responses back to the correct client
- No port conflicts between multiple clients
DNS Server Features
The built-in DNS server provides:
Custom DNS Records
- A Records: Map domain names to IPv4 addresses
- AAAA Records: Map domain names to IPv6 addresses
- CNAME Records: Create domain aliases
- MX Records: Mail server configuration
- TXT Records: Text-based records
- SRV Records: Service discovery records
- NS Records: Name server records
Example DNS Configuration
dns_server:
enabled: true
listen_port: 5353
bind_address: 127.0.0.1
backup_server: 8.8.8.8:53
custom_records:
- name: api.local
type: A
value: 192.168.1.100
ttl: 300
- name: www.local
type: CNAME
value: api.local
ttl: 300
- name: _http._tcp.api.local
type: SRV
value: api.local
ttl: 300
priority: 10
weight: 5
port: 8080
- name: _mysql._tcp.db.local
type: SRV
value: db.local
ttl: 300
priority: 10
weight: 1
port: 3306
DNS Usage
# Test custom DNS records
nslookup api.local localhost -port=5353
nslookup www.local localhost -port=5353
# Test SRV records for service discovery
nslookup -type=SRV _http._tcp.api.local localhost -port=5353
nslookup -type=SRV _mysql._tcp.db.local localhost -port=5353
# Fallback to backup server for unknown domains
nslookup google.com localhost -port=5353
Binary Names
The application provides different binaries for different use cases:
teleport: Main binary (Windows: no console window, Linux: standard)teleport-console: Console version (Windows: shows console window)
Advanced Features
Rate Limiting
Teleport includes configurable rate limiting to prevent abuse:
rate_limit:
enabled: true
requests_per_second: 100 # Maximum requests per second
burst_size: 200 # Maximum burst size
window_size: 1s # Time window for rate limiting
The token bucket is process-global (not per source IP). One noisy peer can consume the budget for everyone; that is enough for a single-user homelab.
Advanced Logging
Teleport includes sophisticated logging with:
- Configurable log levels (debug, info, warn, error)
- Multiple output formats (text, JSON)
- File and console output support
- Automatic sanitization of sensitive data (keys, passwords, tokens)
- Secure file permissions (owner read/write only)
Connection Management
- Connection Pooling: Efficient connection reuse for better performance
- Connection Limits: Configurable maximum concurrent connections
- Health Checks: Automatic detection and cleanup of dead connections
- Graceful Shutdown: Proper cleanup of resources on exit
Notes
- The encryption key must be identical on both server and client
- Use
./teleport --generate-keyto create a raw 256-bit AES key (raw:+ 64 hex). Unprefixed keys in existing configs still use PBKDF2 - The server listens on the specified
listen_addressfor incoming tunnel connections (examples bind loopback;0.0.0.0must be explicit) - The client connects to the remote server and forwards local connections from
bind_address(default127.0.0.1) - All port forwarding is bidirectional
- Port format uses URL-style conventions:
"protocol://target:port" - Configuration files use YAML format for better readability
- The application automatically detects server vs client mode based on configuration
- UDP packets include replay protection and timestamp validation
- All sensitive data in logs is automatically sanitized
- Rate limiting helps prevent abuse and DoS attacks
- Connection pooling improves performance for high-traffic scenarios