Skip to content

Reverse Proxy

Reverse Proxy is a type of proxy service. According to the client's request, the server obtains resources from one or more groups of backend servers (such as web servers) related to it, and then returns these resources to the client. The client only knows the IP address of the reverse proxy, without knowing the existence of server clusters behind proxy servers.

The port forwarding service in GOST can also be regarded as a reverse proxy with limited functions, because it can only forward to a fixed one or a set of backend services.

Reverse proxy is an extension of the port forwarding service, which relies on the port forwarding function, and obtains the target host information in a specific protocol (currently supports HTTP/HTTPS) by sniffing the forwarded data.

Local Port Forwarding

services:
- name: https
  addr: :443
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: google
      addr: www.google.com:443
      host: www.google.com
    - name: github
      addr: github.com:443
      host: "*.github.com"
      # host: .github.com
- name: http
  addr: :80
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:80
      host: example.com
    - name: example-org
      addr: example.org:80
      host: example.org

Use the sniffing option to enable traffic sniffing, and pass the host option in forwarder.nodes to set the (virtual) hostname for each node.

When traffic sniffing is enabled, the forwarding service will obtain the target host through the client’s request data, and then find the final forwarding target address (node.addr) via node.host.

Reverse Proxy - TCP Port Forwarding

node.host also supports wildcards, *.example.com or .example.com matches example.com and its subdomains: abc.example.com, def.abc.example.com, etc.

At this time, the corresponding domain name can be resolved to the local and then accessed through the reverse proxy:

curl --resolve www.google.com:443:127.0.0.1 https://www.google.com
curl --resolve example.com:80:127.0.0.1 http://example.com

Remote Port Forwarding

Remote port forwarding services can also sniff traffic.

services:
- name: https
  addr: :443
  handler:
    type: rtcp
    metadata:
      sniffing: true
  listener:
    type: rtcp
    chain: chain-0
  forwarder:
    nodes:
    - name: local-0
      addr: 192.168.1.1:443
      host: srv-0.local
    - name: local-1
      addr: 192.168.1.2:443
      host: srv-1.local
    - name: fallback
      addr: 192.168.2.1:443
- name: http
  addr: :80
  handler:
    type: rtcp
    metadata:
      sniffing: true
  listener:
    type: rtcp
    chain: chain-0
  forwarder:
    nodes:
    - name: local-0
      addr: 192.168.1.1:80
      host: srv-0.local
    - name: local-1
      addr: 192.168.1.2:80
      host: srv-1.local
chains:
- name: chain-0
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: SERVER_IP:8443 
      connector:
        type: relay
      dialer:
        type: wss

Use the sniffing option to enable traffic sniffing, and pass the host option in forwarder.nodes to set the (virtual) hostname for each node.

Reverse Proxy - Remote TCP Port Forwarding

At this time, the corresponding domain name can be resolved to the server address to access the internal service through the reverse proxy:

curl --resolve srv-0.local:443:SERVER_IP https://srv-0.local
curl --resolve srv-1.local:80:SERVER_IP http://srv-1.local

If the accessed target host does not match the hostname set by the node in the forwarder, when there are nodes without a hostname set, one of these nodes will be selected for use.

curl --resolve srv-2.local:443:SERVER_IP https://srv-2.local

Since srv-2.local does not match the node, it will be forwarded to the fallback node (192.168.2.1:443).

URL Path Routing

Specify the path prefix for the node via the path option. When HTTP traffic is sniffed, the URL path is used to select nodes using the longest prefix matching pattern.

services:
- name: http
  addr: :80
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: target-0
      addr: 192.168.1.1:80
      path: /
    - name: target-1
      addr: 192.168.1.2:80
      path: /test

HTTP Request Header Settings

When sniffing HTTP traffic, you can set the HTTP request header information on the target node through the forwarder.nodes.http option, including Host header rewriting, custom header information and basic auth.

Rewrite Host Header

The Host in the original request header can be overridden by setting the http.host option.

services:
- name: http
  addr: :80
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:80
      host: example.com
      http:
        host: test.example.com
    - name: example-org
      addr: example.org:80
      host: example.org
      http:
        host: test.example.org:80
curl --resolve example.com:80:127.0.0.1 http://example.com

When requesting http://example.com, the Host in the HTTP request header sent to example.com:80 is test.example.com.

Custom Header

The header information can be customized by setting the http.header option, if the header field already exists, it will be overwritten.

services:
- name: http
  addr: :80
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:80
      host: example.com
      http:
        header:
          User-Agent: gost/3.0.0
          foo: bar
          bar: 123
        # host: test.example.com
    - name: example-org
      addr: example.org:80
      host: example.org
      http:
        header:
          User-Agent: curl/7.81.0
          foo: bar
          bar: baz
        # host: test.example.org:80

When requesting http://example.com, three fields User-Agent, Foo and Bar will be added to the HTTP request header sent to example.com:80.

HTTP Basic Authentication

You can enable HTTP Basic Authentication for target node by setting the http.auth option.

services:
- name: http
  addr: :80
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:443
      host: example.com
      http:
        auth:
          username: user
          password: pass

TLS Settings

If the forwarding target node has TLS enabled, you can establish a TLS connection by setting forwarder.nodes.tls.

services:
- name: http
  addr: :80
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:443
      host: example.com
      tls:
        secure: true
        serverName: example.com
        options:
          minVersion: VersionTLS12
          maxVersion: VersionTLS13
          cipherSuites:
          - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
tls.secure (bool, default=false)
Whether to enable server certificate and domain name verification.
tls.serverName (string)
If secure is set to true, you need to specify the server domain name for domain name verification through this parameter.
tls.options.minVersion (string)
Minimum TLS Version, VersionTLS10, VersionTLS11, VersionTLS12 or VersionTLS13.
tls.options.maxVersion (string)
Maximum TLS Version, VersionTLS10, VersionTLS11, VersionTLS12 or VersionTLS13.
tls.options.cipherSuites (list)
Cipher Suites, See Cipher Suites for more information.

Application-Specific Forwarding

Local and remote port forwarding services also support sniffing of specific application traffic. Currently supported application protocols are:

  • http - HTTP traffic.
  • tls - TLS traffic.
  • ssh - SSH traffic.

In forwarder.nodes, specify the node protocol type through the protocol option, and when the corresponding traffic is detected, it will be forwarded to this node.

services:
- name: https
  addr: :443
  handler:
    type: tcp
    metadata:
      sniffing: true
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: http-server
      host: example.com
      addr: example.com:80
      protocol: http
    - name: https-server
      host: example.com
      addr: example.com:443
      protocol: tls
    - name: ssh-server
      addr: example.com:22
      protocol: ssh
services:
- name: https
  addr: :443
  handler:
    type: rtcp
    metadata:
      sniffing: true
  listener:
    type: rtcp
    chain: chain-0
  forwarder:
    nodes:
    - name: local-http
      addr: 192.168.2.1:80
      protocol: http
    - name: local-https
      addr: 192.168.2.1:443
      protocol: tls
    - name: local-ssh
      addr: 192.168.2.1:22
      protocol: ssh
chains:
- name: chain-0
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: SERVER_IP:8443 
      connector:
        type: relay
      dialer:
        type: wss

Forwarding Tunnel

In addition to the original TCP data tunnel can be used as port forwarding, other tunnels can also be used as port forwarding services.

TLS

HTTPS-to-HTTP

The TLS forwarding tunnel can dynamically add TLS support to the backend HTTP service.

services:
- name: https
  addr: :443
  handler:
    type: forward
    metadata:
      sniffing: true
  listener:
    type: tls
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:80
      host: .example.com
    - name: example-org
      addr: example.org:80
      host: .example.org
curl -k --resolve example.com:443:127.0.0.1 https://example.com

HTTP3

HTTP3-to-HTTP.

The HTTP3 forwarding tunnel can dynamically add HTTP/3 support to the backend HTTP service.

services:
- name: http3
  addr: :443
  handler:
    type: http3
  listener:
    type: http3
  forwarder:
    nodes:
    - name: example-com
      addr: example.com:80
      host: .example.com
    - name: example-org
      addr: example.org:80
      host: .example.org
curl -k --http3 --resolve example.com:443:127.0.0.1 https://example.com

Comments