> For the complete documentation index, see [llms.txt](https://adaptix-framework.gitbook.io/adaptix-framework/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adaptix-framework.gitbook.io/adaptix-framework/development/extenders/agent-plugin-in-dev/tunnels.md).

# Tunnels

Tunnels allow proxying network traffic through an agent. SOCKS4/5, Local Port Forward, and Reverse Port Forward are supported.

### Tunnel Types

<table><thead><tr><th width="244">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>TUNNEL_TYPE_SOCKS4</code></td><td>SOCKS4 proxy</td></tr><tr><td><code>TUNNEL_TYPE_SOCKS5</code></td><td>SOCKS5 proxy</td></tr><tr><td><code>TUNNEL_TYPE_SOCKS5_AUTH</code></td><td>SOCKS5 proxy with authentication</td></tr><tr><td><code>TUNNEL_TYPE_LOCAL_PORT</code></td><td>Local port forward (Server → Agent → Target)</td></tr><tr><td><code>TUNNEL_TYPE_REVERSE</code></td><td>Reverse port forward (Agent → Server → Target)</td></tr><tr><td><code>TUNNEL_TYPE_SOCKS_BIND</code></td><td>SOCKS bind. The agent listens; the teamserver completes the channel with <code>TsTunnelConnectionBindReply</code></td></tr></tbody></table>

### Flow (SOCKS/Local Port Forward)

<figure><img src="https://2104178602-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FS8p8XLFtLmf0NkofQvoa%2Fuploads%2F2LApgsp65yvq0YBBcNiS%2F05.png?alt=media&amp;token=efb7047a-eb05-4cf3-bba4-a09af1596aa2" alt=""><figcaption></figcaption></figure>

```
┌──────────────────────────────────────────────────────────────────────────────────┐
│                          TUNNEL FLOW (SOCKS/LPORTFWD)                            │
├──────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          CREATE TUNNEL                                     ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  GUI ──> POST /tunnel/start/socks5 (socks5 start 127.0.0.1:1080)                 │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsTunnelCreateSocks5(AgentId, Info, Lhost, Lport, ...)                     │ │
│  │         │                                                                   │ │
│  │         ├──> Create Tunnel object with agent Callbacks                       │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsTunnelStart(TunnelId)                                                    │ │
│  │         │                                                                   │ │
│  │         └──> net.Listen("tcp", "127.0.0.1:1080")                            │ │
│  │              Start Accept() goroutine for incoming connections             │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          CLIENT CONNECTION                                 ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Browser/App ──> TCP connect to 127.0.0.1:1080                                   │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER (TunnelManager)                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  handleTunChannelCreate()                                                   │ │
│  │         │                                                                   │ │
│  │         ├──> Generate unique channelId                                      │ │
│  │         ├──> proxy.CheckSocks5() ←── Parse SOCKS handshake                  │ │
│  │         ├──> Create TunnelChannel with Pipes                                │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER (Agent Plugin)                                               │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  TunnelCallbacks.ConnectTCP(channelId, host, port)                    │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> return TaskData (added to agent queue)                   │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          AGENT RESPONSE                                    ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Agent ──> COMMAND_TUNNEL_OPEN / COMMAND_TUNNEL_CLOSE                            │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ EXTENDER (Agent Plugin - ProcessData)                                       │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ TEAMSERVER                                                            │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> Success: TsTunnelConnectionResume(channelId)             │  │ │
│  │  │         │         └──> proxy.ReplySocks5Status(SUCCESS)               │  │ │
│  │  │         │              Start relay goroutines                         │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> Failed: TsTunnelConnectionHalt(channelId, errorCode)     │  │ │
│  │  │                   └──> proxy.ReplySocks5Status(ERROR)                 │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          DATA FLOW (bidirectional)                         ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Browser ──write──> Socket ──> pwSrv ──> prSrv ──read──>                         │
│         ──> TunnelCallbacks.WriteTCP(channelId, data)                            │
│                 ──> TaskData ──> Agent ──> Target                                │
│                                                                                  │
│  Target ──> Agent ──> TsTunnelConnectionData(channelId, data)                    │
│         ──> pwTun ──> prTun ──read──> Socket ──write──> Browser                  │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          CONNECTION CLOSE                                  ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Browser closes ──> TunnelCallbacks.Close(channelId) ──> TaskData ──> Agent      │
│  Agent closes   ──> TsTunnelConnectionClose(channelId, write) ──> Close Socket   │
│                                                                                  │
└──────────────────────────────────────────────────────────────────────────────────┘
```

### Flow Reverse Port Forward

<figure><img src="https://2104178602-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FS8p8XLFtLmf0NkofQvoa%2Fuploads%2FC4Mpch5EQryYWavaRyqo%2F06.png?alt=media&amp;token=66e600a8-8e06-43bb-92f0-8ee77aaf57c7" alt=""><figcaption></figcaption></figure>

```
┌──────────────────────────────────────────────────────────────────────────────────┐
│                          REVERSE PORT FORWARD FLOW                               │
├──────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          CREATE RPORTFWD                                   ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  GUI ──> POST /tunnel/start/rportfwd (rportfwd 8080 127.0.0.1:80)                │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsTunnelCreateRportfwd(AgentId, Info, 8080, "127.0.0.1", 80)               │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER (Agent Plugin)                                               │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  TunnelCallbacks.Reverse(tunnelId, 8080)                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> return TaskData ──> Agent listens on port 8080           │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          REMOTE CLIENT CONNECTION                          ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Remote Client ──> TCP connect to Agent:8080                                     │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ EXTENDER (Agent Plugin - ProcessData)                                       │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  Agent sends COMMAND_TUNNEL_OPEN(tunnelId, channelId)                       │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ TEAMSERVER                                                            │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  TsTunnelConnectionAccept(tunnelId, channelId)                        │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> net.Dial("tcp", "127.0.0.1:80")                          │  │ │
│  │  │              Relay: Agent:8080 ←→ Server ←→ 127.0.0.1:80              │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
└──────────────────────────────────────────────────────────────────────────────────┘
```

### Teamserver API for Tunnel

```go
type Teamserver interface {
    TsTunnelCreateSocks4(AgentId int64, Info string, Lhost string, Lport int) (int64, error)
    TsTunnelCreateSocks5(AgentId int64, Info string, Lhost string, Lport int, UseAuth bool, Username string, Password string) (int64, error)
    TsTunnelCreateLportfwd(AgentId int64, Info string, Lhost string, Lport int, Thost string, Tport int) (int64, error)
    TsTunnelCreateRportfwd(AgentId int64, Info string, Lport int, Thost string, Tport int) (int64, error)

    TsTunnelStart(TunnelId int64) (int64, error)
    TsTunnelStop(TunnelId int64) error
    TsTunnelStopSocks(AgentId int64, Port int)
    TsTunnelStopLportfwd(AgentId int64, Port int)
    TsTunnelStopRportfwd(AgentId int64, Port int)
    TsTunnelUpdateRportfwd(tunnelId int64, result bool) (int64, string, error)

    TsTunnelChannelExists(channelId int64) bool
    TsTunnelGetPipe(AgentId int64, channelId int64) (*io.PipeReader, *io.PipeWriter, error)
    TsTunnelConnectionData(channelId int64, data []byte)
    TsTunnelConnectionResume(AgentId int64, channelId int64, ioDirect bool)
    TsTunnelConnectionClose(channelId int64, writeOnly bool)
    TsTunnelConnectionHalt(channelId int64, errorCode byte)
    TsTunnelConnectionAccept(tunnelId int64, channelId int64)
    TsTunnelConnectionBindReply(channelId int64, phase int, atyp int, addr []byte, port int)
    TsTunnelPause(channelId int64)
    TsTunnelResume(channelId int64)
}
```
