Skip to content

hakmarkdev/portme

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PortMe - TCP Port Forwarding

A high-performance TCP port forwarding tool written in Go that allows multiple port forwarding connections to be multiplexed over a single TCP connection between a client and server.

Overview

PortMe enables you to:

  • Forward multiple local ports to remote destinations through a single server connection
  • Reduce the number of open connections and simplify firewall configurations
  • Manage port forwarding rules through YAML configuration files

Quick Start

Basic Usage

# Start the server
./bin/server --config configs/server.yaml

# Start the client
./bin/client --config configs/client.yaml

Running Tests

The test script supports two profiles for running the full test stack:

# Run tests with no authentication (default)
./scripts/run-test.sh

# Or explicitly specify no_auth profile
./scripts/run-test.sh no_auth

# Run tests with token authentication
./scripts/run-test.sh token_auth

# Show help and available options
./scripts/run-test.sh --help

Installation

# Build the project
make build

Command Line Usage

Server Command

./bin/server [flags]

Flags:
  --config string    Path to server configuration file (required)

Examples:
  ./bin/server --config configs/server.yaml

Client Command

./bin/client [flags]

Flags:
  --config string    Path to client configuration file (required)

Examples:
  ./bin/client --config configs/client.yaml

Test Profiles and Authentication

Test Script Profiles

The ./scripts/run-test.sh script supports two profiles for testing different configurations:

no_auth Profile (Default)

  • TCP Dummy Server: Port 4321
  • PortMe Server: Port 6060 using configs/server.yaml
  • PortMe Client: Forwards TCP port 6432 using configs/client.yaml
  • Dummy Client: Connects to 127.0.0.1:6432
  • Authentication: Disabled

token_auth Profile

  • Environment Variables: SERVER_AUTH_TOKEN="secret_token", CLIENT_AUTH_TOKEN="secret_token"
  • TCP Dummy Server: Port 4321 (same as above)
  • PortMe Server: Port 6060 using configs/server_auth.yaml
  • PortMe Client: Forwards TCP port 7432 using configs/client_auth.yaml
  • Dummy Client: Connects to 127.0.0.1:6432
  • Authentication: Enabled with token-based authentication

Authentication Configuration

PortMe supports token-based authentication for secure connections. When authentication is enabled:

Server Authentication Configuration

# server_auth.yaml
listen_address: "127.0.0.1"
listen_port: 6060
max_connections: 100
enable_auth_rules: true

# Authentication rules
auth_rules:
  - name: "secure_tunnel"
    remote_address: "127.0.0.1:4321"
    auth_token: "env_SERVER_AUTH_TOKEN"  # Reads from environment variable

log_level: "info"

Client Authentication Configuration

# client_auth.yaml
server_address: "127.0.0.1:6060"
log_level: "info"

forwarding_rules:
  - name: "secure_tunnel"
    remote_address: "127.0.0.1:4321"
    local_port: 6432
    auth_token: "env_CLIENT_AUTH_TOKEN"  # Reads from environment variable

keepalive_interval: "15s"
activity_deadline: "2m"

Environment Variables for Authentication

For the token_auth profile, the script automatically sets these environment variables:

export SERVER_AUTH_TOKEN="secret_token"
export CLIENT_AUTH_TOKEN="secret_token"

Configuration Files

Server Configuration

The server configuration defines the listening parameters and connection limits.

# Server configuration file (server.yaml)
listen_address: "127.0.0.1"     # IP address to bind the server to
listen_port: 6060                # Port to listen on (can be int or string)
log_level: "info"                # Logging level: debug, info, warn, error
max_connections: 100             # Maximum concurrent client connections
enable_auth_rules: false         # Enable/disable authentication

Client Configuration

The client configuration defines forwarding rules and connection parameters.

# Client configuration file (client.yaml)
server_address: "127.0.0.1:6060"  # Server endpoint to connect to
log_level: "info"                   # Logging level: debug, info, warn, error

# Connection timing parameters
keepalive_interval: "15s"           # Interval between keepalive messages
activity_deadline: "60s"            # Maximum idle time before connection timeout

# Port forwarding rules
forwarding_rules:
  - name: "web-server"              # Human-readable rule identifier
    remote_address: "192.168.1.100:80"  # Destination server:port
    local_port: 8080                # Local port to bind and forward
    # auth_token: "optional_token"    # Optional: authentication token for secure connections

  - name: "database"
    remote_address: "10.0.0.50:5432"
    local_port: 5432

  - name: "ssh-access"
    remote_address: "remote.example.com:22"
    local_port: 2222

Multiplexing Protocol

Protocol Overview

PortMe uses a custom multiplexing protocol that allows multiple independent TCP streams to be transmitted over a single TCP connection between the client and server.

┌─────────────────┐    TCP Connection      ┌─────────────────┐
│   Client Side   │ ◄────────────────────► │   Server Side   │
│                 │                        │                 │
│ ┌─────────────┐ │                        │ ┌─────────────┐ │
│ │ Local Port  │ │                        │ │ Connection  │ │
│ │    8080     │ │ ◄─ Stream 1 ─────────► │ │   Handler   │ │
│ └─────────────┘ │                        │ └─────────────┘ │
│                 │                        │                 │
│ ┌─────────────┐ │                        │ ┌─────────────┐ │
│ │ Local Port  │ │ ◄─ Stream 2 ─────────► │ │ Connection  │ │
│ │    5432     │ │                        │ │   Handler   │ │
│ └─────────────┘ │                        │ └─────────────┘ │
│                 │                        │                 │
└─────────────────┘                        └─────────────────┘

Frame Structure

All data is transmitted using a 12-byte header followed by payload data:

┌─────────────────────────────────────────────────────────┐
│                    Frame Header (12 bytes)              │
├─────────────┬─────────────┬─────────────────────────────┤
│ Stream ID   │ Payload Len │ Control Messages            │
│ (4 bytes)   │ (4 bytes)   │ (4 bytes)                   │
├─────────────┼─────────────┼─────────────────────────────┤
│                   Payload Data (variable)               │
│            (Max: 16MB per frame)                        │
└─────────────────────────────────────────────────────────┘

Header Fields

  • Stream ID (4 bytes): Unique identifier for each multiplexed stream
  • Payload Length (4 bytes): Length of the data payload in bytes
  • Control Messages (4 bytes): Stream control flags and metadata

Forwarding Scenarios

Web Server Access

Forward local port 8080 to a remote web server through the multiplexer.

# client.yaml
forwarding_rules:
  - name: "internal-web"
    remote_address: "internal.company.com:80"
    local_port: 8080

Usage Flow:

  1. Start the server: ./bin/server --config configs/server.yaml
  2. Start the client: ./bin/client --config configs/client.yaml
  3. Access the remote web server locally: http://localhost:8080

Connection Lifecycle

1. Initialization

Client                    Server
  |                        |
  |  TCP Connection        |
  |----------------------->|
  |                        |
  |  Client Hello          |
  |----------------------->|
  |                        |
  |  Server Hello          |
  |<-----------------------|
  |                        |

2. Stream Establishment

Client                    Server                    Remote Target
  |                        |                         |
  |  STREAM_OPEN           |                         |
  |  (rule: "web")         |                         |
  |----------------------->|                         |
  |                        |                         |
  |  STREAM_OPEN_ACK       |                         |
  |<-----------------------|                         |
  |                        |                         |
  |                        |  TCP Connect            |
  |                        |------------------------>|
  |                        |                         |
  |                        |  Connection Established |
  |                        |<------------------------|
  |                        |                         |

3. Data Transfer

Local App               Client                Server              Remote Service
    |                    |                     |                     |
    | HTTP Request       |                     |                     |
    |------------------> |                     |                     |
    |                    | STREAM_DATA         |                     |
    |                    | (stream_id: 1)      |                     |
    |                    |------------------>  |                     |
    |                    |                     | Forwarded Request   |
    |                    |                     |-------------------> |
    |                    |                     |                     |
    |                    |                     | HTTP Response       |
    |                    |                     |<------------------- |
    |                    | STREAM_DATA         |                     |
    |                    | (stream_id: 1)      |                     |
    |                    |<------------------  |                     |
    | HTTP Response      |                     |                     |
    |<------------------ |                     |                     |
    |                    |                     |                     |

4. Connection Teardown

Client                    Server
  |                        |
  |  STREAM_CLOSE          |
  |  (stream_id: 1)        |
  |----------------------->|
  |                        |
  |  STREAM_CLOSE_ACK      |
  |  (stream_id: 1)        |
  |<-----------------------|
  |                        |
  |  Repeat for all        |
  |  active streams        |
  |                        |
  |  CONNECTION_CLOSE      |
  |----------------------->|
  |                        |
  |  CONNECTION_CLOSE_ACK  |
  |<-----------------------|
  |                        |
  |  TCP Connection        |
  |  Closed                |

Monitoring and Logging

Log Levels

  • debug: Detailed protocol frames and connection events
  • info: Connection establishment, stream creation/termination
  • warn: Connection errors and retry attempts
  • error: Critical failures and connection drops

Example Log Output

# Server logs
INFO  Server started successfully listen_address="127.0.0.1:6060" max_connections=100
INFO  Client connected client_id="127.0.0.1:52342"
DEBUG Received data from client client_id="127.0.0.1:52342" bytes=512
INFO  Client connection closed client_id="127.0.0.1:52342"

# Client logs
INFO  Connected to server server_addr="127.0.0.1:6060"
INFO  Started port forwarding listener listen_addr="127.0.0.1:8080" remote_addr="web.example.com:80" rule="web-server"
DEBUG Forwarded data direction="local->remote" bytes=1024
INFO  Established forwarding connection local_addr="127.0.0.1:52344" remote_addr="web.example.com:80"

Performance Considerations

Connection Limits

  • Max Payload Size: 16MB per frame
  • Default Buffer Size: 4KB
  • Max Connections: 100 concurrent client connections
  • Keepalive Interval: 15 seconds (configurable)

Requirements

  • Go 1.17 or higher

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

A high-performance TCP port forwarding tool written in Go.

Topics

Resources

Stars

Watchers

Forks