No description
  • Go 97.7%
  • Shell 2.1%
  • Makefile 0.2%
Find a file
2026-10-24 08:28:45 +00:00
.forgejo/workflows build: Add a toolchain preflight and pin CI actions 2026-10-24 08:10:18 +00:00
cmd/teleport Harden config perms and key derivation 2026-09-01 04:22:57 +00:00
internal Harden config perms and key derivation 2026-09-01 04:22:57 +00:00
pkg Harden config perms and key derivation 2026-09-01 04:22:57 +00:00
scripts build: Add a toolchain preflight and pin CI actions 2026-10-24 08:10:18 +00:00
.gitignore Add initial project structure with core functionality 2025-09-20 18:07:08 -05:00
.goreleaser.yaml Add initial project structure with core functionality 2025-09-20 18:07:08 -05:00
CONTRIBUTING.md docs: Add CONTRIBUTING.md 2026-09-01 13:38:00 -05:00
go.mod build: Add a toolchain preflight and pin CI actions 2026-10-24 08:10:18 +00:00
go.sum Add initial project structure with core functionality 2025-09-20 18:07:08 -05:00
LICENSE Add initial project structure with core functionality 2025-09-20 18:07:08 -05:00
Makefile build: Add a toolchain preflight and pin CI actions 2026-10-24 08:10:18 +00:00
README.md build: Add a toolchain preflight and pin CI actions 2026-10-24 08:10:18 +00:00

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 on 127.0.0.1:9000 → Server forwards to remote web server at 192.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 at 192.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 instance
  • listen_address: Address the server binds for the encrypted tunnel (host:port). Examples use 127.0.0.1:9000. Use 0.0.0.0:9000 or :9000 only when you intend to publish the server on all interfaces.
  • remote_address: Address of remote teleport server (client mode) - format: host:port
  • bind_address: Host for client local TCP/UDP listeners (default: 127.0.0.1). Set to 0.0.0.0 to 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 on bind_address:localport (default 127.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 on 127.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 on 127.0.0.1:5353, forward to teleport server's port 53
  • encryption_key: Shared secret (must be the same on both sides). New keys from --generate-key / --generate-config are raw: 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-key and update both sides together; do not strip raw: from a new key or add raw: 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 duration
  • write_timeout: Write timeout duration
  • max_connections: Maximum concurrent connections (default: 1000 for server, 100 for client)
  • rate_limit: Rate limiting configuration
    • enabled: Enable rate limiting
    • requests_per_second: Maximum requests per second
    • burst_size: Maximum burst size
    • window_size: Time window for rate limiting
  • dns_server: DNS server configuration
    • enabled: Enable built-in DNS server
    • listen_port: Port for DNS server to listen on
    • bind_address: DNS listen host (default: 127.0.0.1). Set to 0.0.0.0 to 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 records
      • name: 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 seconds
      • priority: Priority for MX and SRV records (optional)
      • weight: Weight for SRV records (optional)
      • port: Port for SRV records (optional)

Quick Start

  1. Generate a secure encryption key:

    ./teleport --generate-key
    
  2. Generate configuration files:

    ./teleport --generate-config --config server.yaml
    ./teleport --generate-config --config client.yaml
    
  3. Edit the configs and replace the encryption key with the one you generated

  4. Start the server:

    ./teleport --config server.yaml
    
  5. 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 on 127.0.0.1:localport (or bind_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_address is set and remote_address is empty
  • Client Mode: When remote_address is set and listen_address is 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_address and remote_address configured
  • Neither address set: You have neither listen_address nor remote_address configured

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.1 by default so LAN/internet hosts cannot use your tunnel unless you set bind_address / a per-rule host to 0.0.0.0

Example Use Cases

  1. SSH Tunneling: Forward SSH connections through a secure tunnel
  2. Database Access: Securely access remote databases
  3. Web Services: Forward HTTP/HTTPS traffic
  4. DNS Services: Forward DNS queries (UDP port 53)
  5. NTP Services: Forward time synchronization (UDP port 123)
  6. SNMP Monitoring: Forward SNMP queries (UDP port 161)
  7. Custom Services: Forward any TCP or UDP-based service
  8. Local DNS Resolution: Serve custom DNS records for local development
  9. DNS Override: Override specific domains with custom IP addresses
  10. Service Discovery: Use SRV records for service discovery and load balancing

Example Setup

  1. 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
  2. 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

Multi-Client Support

Multiple clients can connect to the same server using packet tagging:

  1. Start Server: ./teleport -config teleport-server.yaml
  2. Start Client 1: ./teleport -config teleport-client.yaml
  3. 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_id in 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-key to 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_address for incoming tunnel connections (examples bind loopback; 0.0.0.0 must be explicit)
  • The client connects to the remote server and forwards local connections from bind_address (default 127.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