outlinefoundation/tunnel-server

repository·master·Indexed 21 days ago

https://github.com/outlinefoundation/tunnel-server

A high-performance Shadowsocks backend used by the Outline Server. It supports multi-user access on a single port, replay protection, and Prometheus-based monitoring. The project includes the outline-ss-server binary and an outlinecaddy module for integration with Caddy, supporting TCP, UDP, and websocket-based listeners.

Tokens
7.3K
Snippets
26
Records
37
Agent score
73%

What's inside tunnel-server

  1. Full working example: Setup and verify Shadowsocks

    master

    To test the server locally, follow these steps in sequence:

    1. Start the server: Run the server with a sample config and metrics enabled.
    2. Start Prometheus: Use a Prometheus configuration file to scrape the server metrics.
    3. Start the client: Use go-shadowsocks2 to create a SOCKS proxy.
    4. Verify connection: Use curl through the SOCKS proxy to fetch a webpage.
    5. Check metrics: Access the Prometheus metrics endpoint via browser or API.
    # 1. Run the server
    go run ./cmd/outline-ss-server -config cmd/outline-ss-server/config_example.yml -metrics localhost:9091 --replay_history=10000
    
    # 2. Run Prometheus scraper
    prometheus --config.file=cmd/outline-ss-server/prometheus_example.yml
    
    # 3. Run SOCKS-to-Shadowsocks client
    go run github.com/shadowsocks/go-shadowsocks2@latest -c ss://chacha20-ietf-poly1305:Secret0@:9000 -verbose -socks localhost:1080
    
    # 4. Fetch a page over Shadowsocks
    curl --proxy socks5h://localhost:1080 example.com
    
    # 5. Check metrics
    curl http://localhost:9091/metrics
  2. Enable client replay protection in outline-ss-server

    master

    Outline includes a defense against client replay attacks by storing a 32-bit checksum of every valid incoming handshake in a hash table. This feature is enabled by default. If you are running outline-ss-server directly, you can manually configure the size of the replay history using the --replay_history flag.

    Each checksum consumes approximately 20 bytes of memory. For example, setting it to 10000 will store 10,000 checksums.

    # Example: Invoking outline-ss-server with a specific replay history size
    ./outline-ss-server --replay_history 10000
  3. Perform performance testing with iperf3

    master

    To benchmark the Shadowsocks tunnel, use iperf3 to test TCP and UDP throughput. You must first start an iperf3 server, then start the outline-ss-server, and finally start a tunnel using go-shadowsocks2 to redirect traffic through the proxy.

    Steps:

    1. Start iperf3 -s.
    2. Start outline-ss-server.
    3. Start the tunnel (e.g., redirecting port 8000 to the iperf3 server on 5201).
    4. Run iperf3 client commands against the redirected port.
    # Start iperf3 server
    iperf3 -s
    
    # Start SS server
    go run ./cmd/outline-ss-server -config cmd/outline-ss-server/config_example.yml
    
    # Start SS tunnel (redirecting 8000 -> 5201 via proxy on 9000)
    go run github.com/shadowsocks/go-shadowsocks2@latest -c ss://chacha20-ietf-poly1305:Secret0@:9000 -tcptun ":8000=localhost:5201" -udptun ":8000=localhost:5201" -verbose
    
    # Test TCP upload
    iperf3 -c localhost -p 8000
    
    # Test TCP download
    iperf3 -c localhost -p 8000 --reverse
    
    # Test UDP upload
    iperf3 -c localhost -p 8000 --udp -b 0
    
    # Test UDP download
    iperf3 -c localhost -p 8000 --udp -b 0 --reverse
  4. Run the Outline ss-server

    master

    The outline-ss-server command starts the Shadowsocks backend. It supports multiple users on a single port by attempting all provided credentials until one succeeds. You can enable replay protection, configure Prometheus metrics, and provide MMDB files for geographic/ASN metrics breakdown.

    Recommended production command structure:

    outline-ss-server -replay_history=10000 -metrics=127.0.0.1:9091 -config=$CONFIG_YML -ip_country_db=$COUNTRY_MMDB -ip_asn_db=$ASN_MMDB
    outline-ss-server -replay_history=10000 -metrics=127.0.0.1:9091 -config=$CONFIG_YML -ip_country_db=$COUNTRY_MMDB -ip_asn_db=$ASN_MMDB
  5. Run project tests and benchmarks

    master

    Use the task runner to execute the project's test suite and benchmarks.

    To benchmark the cipher finding code specifically, use go test with profiling enabled:

    go test -cpuprofile cpu.prof -memprofile mem.prof -bench . -benchmem -run=^$ github.com/Jigsaw-Code/outline-ss-server/shadowsocks

    You can inspect the resulting profiles using go tool pprof:

    go tool pprof cpu.prof
    # Inside pprof, type 'web' to view the graph
    go run github.com/go-task/task/v3/cmd/task test
  6. Build and run Caddy with the Outline Shadowsocks module

    master

    To use the Outline Shadowsocks backend within Caddy, you must build a custom Caddy binary using xcaddy that includes the outlinecaddy module along with the caddy-l4 and caddy_yaml_adapter dependencies. Once built, you can run the server using a YAML configuration file.

    After starting the server, you can verify the Shadowsocks backend is working by using the Outline SDK to fetch a page over the configured transport.

    xcaddy build \
      --with github.com/iamd3vil/caddy_yaml_adapter \
      --with github.com/mholt/caddy-l4 \
      --with github.com/Jigsaw-Code/outline-ss-server/outlinecaddy
    ./caddy run --config examples/simple.yaml --adapter yaml --watch
  7. Use ConnectionHandler to share handlers across Caddy apps

    master

    A ConnectionHandler is a named, reusable connection handler designed to be configured within the Outline app and shared across different applications (e.g., sharing a Shadowsocks handler between the layer4 app and an HTTP app).

    It works by wrapping a layer4.NextHandler. By assigning a Name to the handler, you can reference the same underlying service configuration in multiple places in your Caddy configuration, ensuring consistency across different protocol stacks.

    To use it, define a ConnectionHandler with a name and provide the raw JSON configuration for the underlying handler in the handle field.

    {
      "name": "my-shared-shadowsocks",
      "handle": {
        ""// configuration for the actual layer4 handler"" : ""
      }
    }
  8. Connection types in OutlineHandler

    master

    The OutlineHandler identifies the underlying protocol of a connection and sets a context variable layer4.handlers.outline.cxtype. This allows downstream handlers to know how to process the connection.

    Supported types:

    • stream: Assigned when the connection implements transport.StreamConn.
    • packet: Assigned when the connection implements net.Conn (standard network connection).

    These are represented by the ConnectionType type constants:

    • StreamConnectionType ("stream")
    • PacketConnectionType ("packet")
  9. How OutlineServer handles configuration hot-swapping

    master

    The OutlineServer supports hot-swapping configurations without stopping the entire process. When loadConfig is called (either manually or via SIGHUP):

    1. The new configuration is read and validated.
    2. New listeners (TCP, UDP, or Web) are created for the new configuration.
    3. The old configuration's stopConfig function is called to close the previous listeners.
    4. The server's internal stopConfig pointer is updated to the new one.

    This approach ensures that there is a period where both old and new listeners coexist, minimizing downtime during configuration updates.

  10. Verify Shadowsocks connectivity using the Outline SDK

    master

    After running the Caddy server with the Outline module, use the following command to confirm you can successfully fetch a page over the Shadowsocks transport. Replace the transport string with your specific protocol and credentials.

    go run golang.getoutline.org/sdk/x/examples/fetch \
      -transport "ss://chacha20-ietf-poly1305:Secret1@:9000" \
      http://ipinfo.io
  11. Configure OutlineHandler connection_handler

    master
    When configuring the OutlineHandler in your Caddyfile or JSON configuration, you must provide the connection_handler key. This value must match the name of a handler previously configured within the OutlineApp module. If this is not specified or if the name does not match an existing handler, the module will fail validation or provisioning.