Write generated configs 0600, treat new keys as raw AES-256, keep PBKDF2 for unprefixed material, and cache derivation at startup.
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
go build -o teleport cmd/teleport/main.go
# Or use the pre-built binaries from releases
# Windows: teleport.exe (no console) or teleport-console.exe (with console)
# Linux: teleport
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