你的位置:首页 > 互联网IT
gost,gost3,gost-v3,gost3配置文件教材,http代理,socks5代理,转发端口,shadowsocks代理,SS代理,负载均衡,中转服务,端口映射,gost3命令教材,教程,T
gost,gost3,gost-v3,gost3配置文件教材,http代理,socks5代理,转发端口,shadowsocks代理,SS代理,负载均衡,中转服务,端口映射,gost3命令教材,教程,TLS设置,HTTP通道
系统:Windows/linux
软件:gost v3.0
功能:http代理,socks5代理,转发端口,shadowsocks代理,SS代理,负载均衡,中转服务,端口映射
项目地址:https://github.com/go-gost/gost
gost-v3-beta.6(使用很久,稳定版本)
本地下载1-Windows-32位:gost-windows-386-3.0.0-beta.6.zip
本地下载2-Windows-64位:gost-windows-amd64-3.0.0-beta.6.zip
本地下载3-linux-32位:gost-linux-386-3.0.0-beta.6.gz
本地下载4-linux-64位:gost-linux-amd64-3.0.0-beta.6.gz
gost-v3.0.0-rc8
本地下载5-Windows-32位:gost_3.0.0-rc8_windows_386.zip
本地下载6-Windows-64位:gost_3.0.0-rc8_windows_amd64.zip
本地下载7-linux-32位:gost_3.0.0-rc8_linux_386.tar.gz
本地下载8-linux-64位:gost_3.0.0-rc8_linux_amd64.tar.gz
项目地址下载地址:https://github.com/go-gost/gost/releases
本文内容:教程,TLS设置,HTTP通道,端口转发,反向代理,反向代理隧道,反向代理隧道-高可用,HTTP文件服务
gost,gost3,gost-v3版本-配置文件文章
https://www.zhuguodong.com/?id=771
gost,gost3,gost-v3版本-命令文章
https://www.zhuguodong.com/?id=767
同类型gost-v2.0(gost2)版本
https://www.zhuguodong.com/?id=700
-----------------------------------------------------------
Windows隐藏运行软件,cmd隐藏运行,bat隐藏运行,命令窗口隐藏运行
https://www.zhuguodong.com/?id=520
linux隐藏运行软件
nohup /root/gost -L ss://aes-256-cfb:123456@:23333 >/dev/null 2>&1 &
nohup 《内容替换》 >/dev/null 2>&1 &
-----------------------------------------------------------
简单配置运行:
Windows:新建 gost.bat 文件
linux:命令窗口隐藏运行,gost要加入权限:chmod +x gost
启动参数:-c
Windows:start "" "gost.exe" -C gost.yaml
linux:gost -C gost.yaml
说明:.yaml配置文件不能有空行,或者不必要的空格,不然会运行不成功
启动参数:-c
Windows:start "" "gost.exe" -C gost.json
linux:gost -C gost.json
程序gost与文件同一目录下,说明:.json与.yaml配置文件格式(这个文件格式配置不能出现空格),教材就用.json格式演示
配置.json与.yaml格式可相互转换的
输出yaml格式配置
gost -L http://:8080 -O yaml
输出json格式配置
gost -L http://:8080 -O json
将json格式配置转成yaml格式
gost -C gost.json -O yaml
gost -C gost.yaml -O json
-----------------------------------------------------------
TLS¶
GOST有三种类型TLS证书:自生成证书,全局证书,服务层级证书。
自生成证书¶
GOST在每次运行时自动生成TLS证书,如果未指定任何证书,会使用此证书作为默认证书。
自定义证书信息¶
命令行
命令行模式下暂不支持设置全局证书。
validity (duration, default=8760h)
证书有效期,默认1年。
commonName (string, default=gost.run)
证书CN信息。
organization (string, default=GOST)
证书的Organization信息。
配置文件
tls:
validity: 8760h
commonName: gost.run
organization: GOST
validity (duration, default=8760h)
证书有效期,默认1年。
commonName (string, default=gost.run)
证书CN信息。
organization (string, default=GOST)
证书的Organization信息。
全局证书¶
全局证书默认使用自动生成的证书,也可以通过配置指定自定义证书文件。
命令行
命令行模式下暂不支持设置全局证书。
配置文件
tls:
certFile: "cert.pem"
keyFile: "key.pem"
caFile: "ca.pem"
提示
GOST会自动加载当前工作目录下的cert.pem, key.pem, ca.pem文件来初始化全局证书。
服务层级证书¶
每个服务的监听器和处理器可以分别设置各自的证书,默认使用全局证书。
命令行
gost -L http+tls://:8443?certFile=cert.pem&keyFile=key.pem&caFile=ca.pem
配置文件
services:
- name: service-0
addr: :8443
handler:
type: http
listener:
type: tls
tls:
certFile: cert.pem
keyFile: key.pem
caFile: ca.pem
客户端设置¶
客户端可以对每个节点的拨号器和连接器分别设置证书。
命令行
gost -L http://:8080 -F tls://IP_OR_DOMAIN:8443?secure=true&serverName=www.example.com
配置文件
services:
- name: service-0
addr: :8080
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.1:8443
connector:
type: http
dialer:
type: tls
tls:
secure: true
serverName: www.example.com
caFile (string)
CA证书文件路径。设置CA证书将会开启证书锁定(Certificate Pinning)。
secure (bool, default=false)
开启服务器证书和域名校验。
serverName (string)
若secure设置为true,则需要通过此参数指定服务器域名用于域名校验。默认使用设置中IP_OR_DOMAIN作为serverName。
TLS选项¶
services:
- name: service-0
addr: :8443
handler:
type: http
listener:
type: tls
tls:
options:
minVersion: VersionTLS12
maxVersion: VersionTLS13
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
minVersion (string)
TLS最小版本,可选值VersionTLS10,VersionTLS11,VersionTLS12,VersionTLS13。
maxVersion (string)
TLS最大版本,可选值VersionTLS10,VersionTLS11,VersionTLS12,VersionTLS13。
cipherSuites (list)
加密套件,可选值参考Cipher Suites。
双向证书校验¶
如果服务端设置了CA证书,则会对客户端证书进行强制校验,此时客户端须提供证书。
命令行
gost -L http://:8080 -F tls://IP_OR_DOMAIN:8443?certFile=cert.pem&keyFile=key.pem
配置文件
services:
- name: service-0
addr: :8080
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.1:8443
connector:
type: http
dialer:
type: tls
tls:
certFile: cert.pem
keyFile: key.pem
注意
通过命令行设置的证书信息仅会应用到监听器或拨号器上。
-----------------------------------------------------------
HTTP数据通道¶
HTTP是目前互联网上使用最广泛的一种数据交换协议,随着互联网的发展,协议也进行了几次重大的版本升级,从最原始的HTTP/1到HTTP/2,再到现在的基于QUIC协议的HTTP/3。
原始HTTP协议是一种请求响应式的交互方式,由客户端主动发起请求,服务端收到请求后再将处理结果发送回客户端,这种方式无法在客户端和服务端之间保持长连接,因此很难做到双向实时数据传输。为了实现全双工通信,HTTP协议又进行了多种扩展,例如增加CONNECT方法,Websocket扩展协议,HTTP/2的服务端推送和HTTP/3的WebTransport等。GOST已经支持了以上大部分的功能。
注意
CONNECT方法用于HTTP建立代理连接,严格来说不能称之为数据通道,然而其本质都是建立了可以双向通讯的长连接,所以在这里统一被当作数据通道。
HTTP CONNECT方法¶
服务端¶
命令行
gost -L http://user:pass@:8080
配置文件
services:
- name: service-0
addr: ":8080"
handler:
type: http
auth:
username: user
password: pass
listener:
type: tcp
以上是一个最简单的带有认证功能的HTTP代理服务。
客户端¶
命令行
gost -L http://:8000 -F http://user:pass@:8080
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8080
connector:
type: http
auth:
username: user
password: pass
dialer:
type: tcp
客户端本身也是一个HTTP代理服务,并通过转发链将请求转发给上面的HTTP代理服务。
Plain HTTP Tunnel(pht)¶
CONNECT方法并不是所有服务都支持,为了尽可能通用,GOST利用原始HTTP协议中的GET和POST方法来实现数据通道,包括加密的phts和明文的pht两种模式。
服务端¶
命令行
gost -L relay+pht://:8080?authorizePath=/authorize&pushPath=/push&pullPath=/pull
或
gost -L relay+phts://:8080
配置文件
services:
- name: service-0
addr: ":8080"
handler:
type: relay
listener:
type: pht
# type: phts
metadata:
authorizePath: /authorize
pullPath: /pull
pushPath: /push
客户端¶
命令行
gost -L http://:8000 -F relay+pht://:8080?authorizePath=/authorize&pushPath=/push&pullPath=/pull
或
gost -L http://:8000 -F relay+phts://:8080
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8080
connector:
type: relay
dialer:
type: pht
# type: phts
metadata:
authorizePath: /authorize
pullPath: /pull
pushPath: /push
Caution
PHT是一个实验性功能,还在不断完善中。
Websocket¶
Websocket是HTTP/1中为了建立长连接而增加的扩展协议。
服务端¶
命令行
gost -L socks5+ws://user:pass@:1080
配置文件
services:
- name: service-0
addr: ":1080"
handler:
type: socks5
auth:
username: user
password: pass
listener:
type: ws
客户端¶
命令行
gost -L http://:8000 -F socks5+ws://user:pass@:1080
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :1080
connector:
type: socks5
auth:
username: user
password: pass
dialer:
type: ws
注意
这里的认证信息设置的是SOCKS5代理的认证,Websocket暂不支持认证设置。
HTTP/2¶
GOST中HTTP/2有两种使用方式,代理模式和标准数据通道模式。
HTTP/2 CONNECT方法¶
HTTP/2使用与HTTP相同的CONNECT方法实现代理模式。
服务端¶
命令行
gost -L http2://user:pass@:8443
配置文件
services:
- name: service-0
addr: ":8443"
handler:
type: http2
auth:
username: user
password: pass
listener:
type: http2
客户端¶
命令行
gost -L http://:8000 -F http2://user:pass@:8443
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: http2
auth:
username: user
password: pass
dialer:
type: http2
HTTP/2数据通道¶
HTTP/2做为数据通道可以使用加密(h2)和明文(h2c)两种模式。
服务端¶
命令行
gost -L socks5+h2://user:pass@:8443
或
gost -L socks5+h2c://user:pass@:8443
配置文件
services:
- name: service-0
addr: ":8443"
handler:
type: socks5
auth:
username: user
password: pass
listener:
type: h2
# type: h2c
客户端¶
命令行
gost -L http://:8000 -F socks5+h2://user:pass@:8443
或
gost -L http://:8000 -F socks5+h2c://user:pass@:8443
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: socks5
auth:
username: user
password: pass
dialer:
type: h2
# type: h2c
服务端推送
GOST不支持HTTP/2的服务端推送功能。
gRPC¶
gRPC是基于HTTP/2,因此具有HTTP/2本身固有的优点,另外gRPC天然的支持双向流传输,因此很适合作为数据通道。
服务端¶
命令行
gost -L relay+grpc://user:pass@:8443
配置文件
services:
- name: service-0
addr: ":8443"
handler:
type: relay
auth:
username: user
password: pass
listener:
type: grpc
客户端¶
命令行
gost -L http://:8000 -F relay+grpc://user:pass@:8443
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: relay
auth:
username: user
password: pass
dialer:
type: grpc
gRPC默认使用TLS加密,可以通过设置grpcInsecure参数使用明文进行通讯。
服务端¶
命令行
gost -L relay+grpc://user:pass@:8443?grpcInsecure=true
配置文件
services:
- name: service-0
addr: ":8443"
handler:
type: relay
auth:
username: user
password: pass
listener:
type: grpc
metadata:
grpcInsecure: true
客户端¶
命令行
gost -L http://:8000 -F relay+grpc://user:pass@:8443?grpcInsecure=true
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: relay
auth:
username: user
password: pass
dialer:
type: grpc
metadata:
grpcInsecure: true
HTTP/3¶
HTTP/3协议规范中支持CONNECT方法和WebTransport两种方式建立数据通道。
GOST目前不支持以上两种方式,而是通过在HTTP/3之上利用pht来建立数据通道。
WebTransport
WebTransport目前处在早期草案阶段,待时机成熟后GOST会添加对其的支持。
服务端¶
命令行
gost -L "h3://:8443?authorizePath=/authorize&pushPath=/push&pullPath=/pull"
配置文件
services:
- name: service-0
addr: ":8443"
handler:
type: auto
listener:
type: h3
metadata:
authorizePath: /authorize
pullPath: /pull
pushPath: /push
客户端¶
命令行
gost -L http://:8000 -F h3://:8443?authorizePath=/authorize&pushPath=/push&pullPath=/pull
配置文件
services:
- name: service-0
addr: ":8000"
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: http
dialer:
type: h3
metadata:
authorizePath: /authorize
pullPath: /pull
pushPath: /push
-----------------------------------------------------------
端口转发¶
端口转发根据协议类型分为TCP和UDP端口转发,根据转发类型又分为本地转发和远程转发,总共有四种组合。
本地端口转发¶
TCP¶
可以设置单一的转发目标地址进行一对一端口转发
命令行1
gost -L tcp://:8080/:80
配置文件
services:
- name: service-0
addr: :8080
handler:
type: tcp
listener:
type: tcp
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
将本地的TCP端口8080映射到192.168.1.1的80端口,所有到本地8080端口的数据会被转发到192.168.1.1:80。
也可以设置多个目标地址进行一对多端口转发
命令行
gost -L tcp://:8080/192.168.1.1:80,192.168.1.2:80,192.168.1.3:8080?strategy=round&maxFails=1&failTimeout=30s
配置文件
services:
- name: service-0
addr: :8080
handler:
type: tcp
listener:
type: tcp
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
- name: target-1
addr: 192.168.1.2:80
- name: target-1
addr: 192.168.1.3:8080
selector:
strategy: round
maxFails: 1
failTimeout: 30s
在每次收到转发请求后,会利用转发器中的节点选择器在目标地址列表中选择一个节点作为本次转发的目标地址。
UDP¶
和TCP端口转发类似,也可以指定单个和多个目标转发地址。
命令行
gost -L udp://:10053/192.168.1.1:53,192.168.1.2:53,192.168.1.3:53?keepAlive=true&ttl=5s
配置文件
services:
- name: service-0
addr: :10053
handler:
type: udp
listener:
type: udp
metadata:
keepAlive: true
ttl: 5s
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:53
- name: target-1
addr: 192.168.1.2:53
- name: target-2
addr: 192.168.1.3:53
每一个客户端对应一条转发通道,当keepAlive参数设置为false时(默认情况),请求的响应数据返回给客户端后会立即关闭通道连接。
当keepAlive参数设置为true时,转发服务一定时间内收不到转发目标主机数据,此转发通道会被标记为空闲状态。转发服务内部会按照ttl参数(默认值5秒)指定的周期检查转发通道是否空闲,如果空闲则此通道将被关闭。一个空闲通道最多会在两个检查周期内被关闭。
转发链¶
端口转发可以配合转发链进行间接转发。
命令行
gost -L=tcp://:8080/192.168.1.1:80 -F socks5://192.168.1.2:1080
配置文件
services:
- name: service-0
addr: :8080
handler:
type: tcp
chain: chain-0
listener:
type: tcp
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.2:1080
connector:
type: socks5
dialer:
type: tcp
将本地的TCP端口8080通过转发链映射到192.168.1.1的80端口。
命令行
gost -L=udp://:10053/192.168.1.1:53 -F socks5://192.168.1.2:1080
配置文件
services:
- name: service-0
addr: :10053
handler:
type: udp
chain: chain-0
listener:
type: udp
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:53
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.2:1080
connector:
type: socks5
dialer:
type: tcp
将本地的UDP端口10053通过转发链映射到192.168.1.1的53端口。
限制
当UDP本地端口转发中使用转发链时,转发链末端最后一个节点必须是以下类型:
GOST HTTP代理服务并开启了UDP转发功能,采用UDP-over-TCP方式。
gost -L http://:8080?udp=true
GOST SOCKS5代理服务并开启了UDP转发功能,采用UDP-over-TCP方式。
gost -L socks5://:1080?udp=true
Relay服务,采用UDP-over-TCP方式。
SSU服务。
UDP-over-TCP
UDP-over-TCP是指使用TCP连接来传输UDP数据包。在GOST中这个说法可能并不太准确,例如使用SOCKS5进行UDP端口转发,SOCKS5服务可以是基于TCP类型的传输通道(TLS, Websocket等),也可以是基于UDP类型的传输通道(KCP, QUIC等),这里使用UDP-over-Stream更合适一些(相对于UDP不可靠的数据报式传输来说),任何可靠的流式传输协议均可以用在此处。
SSH¶
TCP端口转发可以借助于标准SSH协议的端口转发功能进行间接转发
命令行
gost -L=tcp://:8080/192.168.1.1:80 -F sshd://user:pass@192.168.1.2:22
配置文件
services:
- name: service-0
addr: :8080
handler:
type: tcp
chain: chain-0
listener:
type: tcp
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.2:22
connector:
type: sshd
dialer:
type: sshd
auth:
username: user
password: pass
这里的192.168.1.2:22服务可以是系统本身的标准SSH服务,也可以是GOST的sshd类型服务
命令行
gost -L sshd://user:pass@:22
配置文件
services:
- name: service-0
addr: :22
handler:
type: sshd
listener:
type: sshd
auth:
username: user
password: pass
远程端口转发¶
TCP¶
命令行
gost -L rtcp://:8080/192.168.1.1:80
配置文件
services:
- name: service-0
addr: :8080
handler:
type: rtcp
listener:
type: rtcp
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
将本地的TCP端口8080映射到192.168.1.1的80端口,所有到本地8080端口的数据会被转发到192.168.1.1:80。
UDP¶
命令行
gost -L rudp://:10053/192.168.1.1:53,192.168.1.2:53,192.168.1.3:53?ttl=5s
配置文件
services:
- name: service-0
addr: :10053
handler:
type: rudp
listener:
type: rudp
metadata:
ttl: 5s
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:53
- name: target-1
addr: 192.168.1.2:53
- name: target-2
addr: 192.168.1.3:53
注意
在不使用转发链的情况下,远程端口转发与本地端口转发没有区别。
转发链¶
命令行
gost -L=rtcp://:8080/192.168.1.1:80 -F socks5://192.168.1.2:1080
配置文件
services:
- name: service-0
addr: :8080
handler:
type: rtcp
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.2:1080
connector:
type: socks5
dialer:
type: tcp
根据rtcp服务指定的地址,通过转发链在主机192.168.1.2上监听8080TCP端口。当收到请求后再通过转发链将数据转发给rtcp服务,rtcp服务再将请求转发到192.168.1.1:80端口。
命令行
gost -L=rudp://:10053/192.168.1.1:53 -F socks5://192.168.1.2:1080
配置文件
services:
- name: service-0
addr: :10053
handler:
type: rudp
listener:
type: rudp
chain: chain-0
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:53
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.2:1080
connector:
type: socks5
dialer:
type: tcp
根据rudp服务指定的地址,通过转发链在主机192.168.1.2上监听10053端口。当收到请求后再通过转发链将数据转发给rudp服务,rudp服务再将请求转发到192.168.1.1:53端口。
注意
远程端口转发上的转发链默认设置在监听器上,此时处理器上也可以再设置另外的转发链。
远程端口转发服务中的监听地址,在使用转发链时将监听在转发链末端最后一个节点服务所在的主机上。
限制
当远程端口转发中使用转发链时,转发链末端最后一个节点必须是以下类型:
GOST SOCKS5代理服务并开启了BIND功能,采用UDP-over-TCP方式。
gost -L socks5://:1080?bind=true
Relay服务并开启了BIND功能,采用UDP-over-TCP方式。
gost -L relay://:8421?bind=true
SSH¶
TCP远程端口转发可以借助于标准SSH协议的远程端口转发功能进行间接转发
命令行
gost -L=rtcp://:8080/192.168.1.1:80 -F sshd://user:pass@192.168.1.2:22
配置文件
services:
- name: service-0
addr: :8080
handler:
type: rtcp
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 192.168.1.2:22
connector:
type: sshd
dialer:
type: sshd
auth:
username: user
password: pass
这里的192.168.1.2:22服务可以是系统本身的标准SSH服务,也可以是GOST的sshd类型服务。
服务端转发¶
以上的转发方式可以看作是客户端转发,由客户端来控制转发的目标地址。目标地址也可以由服务端指定。
服务端¶
命令行
gost -L tls://:8443/192.168.1.1:80
配置文件
services:
- name: service-0
addr: :8080
handler:
type: forward
listener:
type: tls
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
客户端¶
命令行
gost -L=tcp://:8080 -F forward+tls://:8443
配置文件
services:
- name: service-0
addr: :8080
handler:
type: tcp
listener:
type: tcp
chain: chain-0
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: forward
dialer:
type: tls
forward类型连接器和处理器
这里服务的处理器和转发链的连接器必须为forward类型,由于目标地址由服务端指定,因此客户端无需指定目标地址。forward连接器不做任何逻辑处理。
这里的tcp://:8080等同于tcp://:8080/:0,转发目标地址:0在这里作为占位符。仅当配合forward连接器使用时,这种用法才是有效的。
-----------------------------------------------------------
反向代理¶
反向代理是代理服务的一种。服务器根据客户端的请求,从其关系的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器集群的存在。
GOST中的端口转发服务也可以被当作是一种功能受限的反向代理,因其只能转发到固定的一个或一组后端服务。
反向代理是端口转发服务的一个扩展,其依托于端口转发功能,并通过嗅探转发的数据来获取特定协议(目前支持HTTP/HTTPS)中的目标主机信息。
关于反向代理更详细的说明可以参考这篇博文。
本地端口转发¶
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
通过sniffing选项来开启流量嗅探,并在forwarder.nodes中通过host选项可以对每一个节点设置(虚拟)主机名。
当开启流量嗅探后,转发服务会通过客户端的请求数据获取访问的目标主机,再通过转发器(forwarder)中的节点设置的虚拟主机名(node.host)找到最终转发的目标地址(node.addr)。
Reverse Proxy - TCP Port Forwarding
node.host也支持通配符,*.example.com或.example.com匹配example.com及其子域名:abc.example.com,def.abc.example.com等。
此时可以将对应的域名解析到本地通过反向代理来访问:
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
远程端口转发¶
远程端口转发服务同样也可以对流量进行嗅探。
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
通过sniffing选项来开启流量嗅探,并在forwarder.nodes中通过host选项可以对每一个节点设置(虚拟)主机名。
Reverse Proxy - Remote TCP Port Forwarding
此时可以将对应的域名解析到服务器地址通过反向代理来访问内网服务:
curl --resolve srv-0.local:443:SERVER_IP https://srv-0.local
curl --resolve srv-1.local:80:SERVER_IP http://srv-1.local
如果访问的目标主机没有与转发器中的节点设定的主机名匹配上,当存在没有设置主机名的节点,则会在这些节点中选择一个使用。
curl --resolve srv-2.local:443:SERVER_IP https://srv-2.local
由于srv-2.local没有匹配到节点,因此会被转发到fallback节点(192.168.2.1:443)。
HTTP请求头设置¶
当嗅探到HTTP流量时,可以在目标节点上通过forwarder.nodes.http选项对HTTP的请求头部信息进行设置,包括Host头重写和自定义头部信息,对本地和远程端口转发均适用。
重写Host头¶
通过设置http.host选项可以重写原始请求头中的Host。
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
当请求http://example.com时,最终发送给example.com:80的HTTP请求头中Host为test.example.com。
自定义头¶
通过设置http.header选项可以自定义头部信息,如果所设置的头部字段已存在则会被覆盖。
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
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
当请求http://example.com时,最终发送给example.com:80的HTTP请求头中将会添加User-Agent,Foo和Bar三个字段。
TLS请求设置¶
如果转发的目标节点启用了TLS,可以通过设置forwarder.nodes.tls来建立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
tls.secure (bool, default=false)
是否开启服务器证书和域名校验。
tls.serverName (string)
若secure设置为true,则需要通过此参数指定服务器域名用于域名校验。
HTTP Basic Authentication¶
可以通过设置forwarder.nodes.auth选项为目标节点启用HTTP基本认证功能。
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
auth:
username: user
password: pass
特定应用转发¶
本地和远程端口转发服务也支持对特定的应用流量嗅探。目前支持的应用协议有:SSH。
SSH¶
在forwarder.nodes中通过protocol选项指定节点协议类型为ssh,当嗅探到SSH协议流量则会转发到此节点。
本地端口转发
services:
- name: https
addr: :443
handler:
type: tcp
metadata:
sniffing: true
listener:
type: tcp
forwarder:
nodes:
- 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-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
优先级
当同时设置了host和protocol选项,仅会按host进行匹配。
转发通道¶
除了原始TCP数据通道可以用来作为端口转发,其他数据通道也可以作为端口转发服务。
TLS转发通道¶
HTTPS-to-HTTP反向代理。
TLS转发通道可以动态的给后端HTTP服务添加TLS支持。
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反向代理。
HTTP3转发通道可以动态的给后端HTTP服务添加HTTP/3支持。
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
-----------------------------------------------------------
反向代理隧道¶
在上一篇反向代理教程中,利用端口转发实现了简单的反向代理功能,在本篇中将利用隧道服务实现类似于Cloudflare Tunnel的增强版反向代理。
隧道(Tunnel)¶
隧道是一条服务端和客户端之间的(逻辑上的)通道,服务端可以开启一个额外的公共入口点(EntryPoint),由入口点进入的流量会通过隧道发送给客户端。每个隧道有一个唯一的ID(合法的UUID),一个隧道可以有多个连接(连接池)来实现隧道的高可用性。
Reverse Proxy - Remote TCP Port Forwarding
服务端¶
命令行
gost -L "tunnel://:8443?entrypoint=:80&tunnel=.example.com:4d21094e-b74c-4916-86c1-d9fa36ea677b,example.org:ac74d9dd-3125-442a-a7c1-f9e49e05faca"
配置文件
services:
- name: service-0
addr: :8443
handler:
type: tunnel
metadata:
entrypoint: ":80"
ingress: ingress-0
listener:
type: tcp
ingresses:
- name: ingress-0
rules:
- hostname: ".example.com"
endpoint: 4d21094e-b74c-4916-86c1-d9fa36ea677b
- hostname: "example.org"
endpoint: ac74d9dd-3125-442a-a7c1-f9e49e05faca
通过entrypoint选项指定流量的公共入口点,同时通过ingress选项指定Ingress对象来定义流量路由规则。
隧道ID分配
如果使用了Ingress,隧道将通过(虚拟)主机名进行路由,隧道的ID应当由服务端提前分配并记录在Ingress中。如果客户端使用了一个未在Ingress中注册的隧道ID,则流量无法路由到此客户端。
客户端¶
命令行
gost -L rtcp://:0/192.168.1.1:80 -F tunnel://:8443?tunnel.id=4d21094e-b74c-4916-86c1-d9fa36ea677b
配置文件
services:
- name: service-0
addr: :0
handler:
type: rtcp
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: 4d21094e-b74c-4916-86c1-d9fa36ea677b
dialer:
type: tcp
通过tunnel.id指定隧道ID,此时rtcp服务中指定的addr参数无效。
本例中当流量进入公共入口点(服务端的80端口)后会嗅探流量信息获取所要访问的主机名,再通过主机名在Ingress中找到匹配的规则,获取对应的服务端点(endpoint即隧道ID),最后在隧道的连接池中获取一个有效连接将流量通过此连接发送到客户端。
当主机名为example.com时,根据Ingress中的规则匹配到ID为4d21094e-b74c-4916-86c1-d9fa36ea677b的隧道。当流量到达客户端后再由rtcp服务转发给192.168.1.1:80服务。
高可用性
为了提高单个隧道的可用性,可以运行多个客户端,这些客户端使用相同的隧道ID。当需要从隧道获取连接时,将采用轮询机制,最多3次失败重试。
外部公共入口点¶
上面通过entrypoint选项设置的入口点可以看作是隧道服务内部提供的一个公共入口点,也可以运行多个外部公共入口点将流量转发到隧道服务。
服务端¶
服务端通过entrypoint.id指定入口点ID,客户端必须使用相同的ID才会被认为是一个公共入口点,否则会被当作私有入口点,仅能访问指定的隧道。
命令行
gost -L "tunnel://:8443?entrypoint.id=9fd6c586-86f9-49c1-a03a-d4876851695a
配置文件
services:
- name: service-0
addr: :8443
handler:
type: tunnel
metadata:
entrypoint.id: 9fd6c586-86f9-49c1-a03a-d4876851695a
ingress: ingress-0
listener:
type: tcp
ingresses:
- name: ingress-0
rules:
- hostname: ".example.com"
endpoint: 4d21094e-b74c-4916-86c1-d9fa36ea677b
- hostname: "example.org"
endpoint: ac74d9dd-3125-442a-a7c1-f9e49e05faca
客户端¶
客户端通过tunnel.id指定隧道ID,当隧道ID与服务端的entrypoint.id相同时,此客户端会被当作一个公共入口点。
命令行
gost -L tcp://:8000?sniffing=true -F tunnel://:8443?tunnel.id=9fd6c586-86f9-49c1-a03a-d4876851695a
配置文件
services:
- name: service-0
addr: :8000
handler:
type: tcp
chain: chain-0
metadata:
sniffing: true
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: 9fd6c586-86f9-49c1-a03a-d4876851695a
dialer:
type: tcp
客户端路由¶
客户端也可以同时开启流量嗅探对流量进行再次路由。
services:
- name: service-0
addr: :0
handler:
type: rtcp
metadata:
sniffing: true
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: example-com
addr: 192.168.1.1:80
host: example.com
- name: sub-example-com
addr: 192.168.1.2:80
host: sub.example.com
- name: fallback
addr: 192.168.2.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: 4d21094e-b74c-4916-86c1-d9fa36ea677b
dialer:
type: tcp
当主机名为example.com时,根据Ingress中的规则匹配到Tunnel 4d21094e-b74c-4916-86c1-d9fa36ea677b。当流量到达客户端后再由rtcp服务转发给192.168.1.1:80服务。
当主机名为sub.example.com时,根据Ingress中的规则匹配到Tunnel 4d21094e-b74c-4916-86c1-d9fa36ea677b。当流量到达客户端后再由rtcp服务转发给192.168.1.2:80服务。
当主机名为abc.example.com时,根据Ingress中的规则匹配到Tunnel 4d21094e-b74c-4916-86c1-d9fa36ea677b。当流量到达客户端后再由rtcp服务转发给192.168.2.1:80服务。
私有隧道¶
在Ingress中可以通过将隧道标记为私有来限制对隧道的访问,由公共入口点进入的流量无法路由到私有隧道。
若要使用私有隧道,用户(访问端)需要开启一个私有入口点将流量转发到指定的隧道,通过设置隧道ID来指定想要访问的隧道(不仅限于私有隧道)。
Reverse Proxy - Web Private Tunnel
服务端¶
services:
- name: service-0
addr: :8443
handler:
type: tunnel
metadata:
entryPoint: ":80"
ingress: ingress-0
listener:
type: tcp
ingresses:
- name: ingress-0
rules:
- hostname: "srv-0.local"
endpoint: 4d21094e-b74c-4916-86c1-d9fa36ea677b
- hostname: "srv-1.local"
endpoint: 4d21094e-b74c-4916-86c1-d9fa36ea677b
- hostname: "srv-2.local"
endpoint: $ac74d9dd-3125-442a-a7c1-f9e49e05faca # private tunnel
- hostname: "srv-3.local"
endpoint: ac74d9dd-3125-442a-a7c1-f9e49e05faca
- hostname: "ssh.srv-2.local"
endpoint: aede1f6a-762b-45da-b937-b6632356555a # tunnel for ssh TCP traffic
- hostname: "redis.srv-3.local"
endpoint: aede1f6a-762b-45da-b937-b6632356555a # tunnel for redis TCP traffic
- hostname: "dns.srv-2.local"
endpoint: aede1f6a-762b-45da-b937-b6632356555a # tunnel for DNS UDP traffic
- hostname: "dns.srv-3.local"
endpoint: aede1f6a-762b-45da-b937-b6632356555a # tunnel for DNS UDP traffic
在Ingress的规则中,通过在endpoint所代表的隧道ID值前添加$便将此规则对应的隧道标记为私有,例如上面的srv-2.local主机对应的隧道ac74d9dd-3125-442a-a7c1-f9e49e05faca即为私有隧道,因此通过公共入口点80端口进入的流量无法使用此隧道。
私有性
私有性的作用范围为Ingress的规则,而不是隧道本身,同一个隧道在不同的规则中可以有不同的私有性。例如上面例子当中,srv-2.local和srv-3.local使用的是相同的隧道,但srv-3.local对应规则中隧道不是私有的,因此通过公共入口点80端口进入去往srv-3.local主机的流量可以路由到此隧道。
客户端¶
命令行
gost -L rtcp://:0/192.168.2.1:80 -F tunnel://:8443?tunnel.id=ac74d9dd-3125-442a-a7c1-f9e49e05faca
配置文件
services:
- name: service-0
addr: :0
handler:
type: rtcp
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: srv-2.local
addr: 192.168.2.1:80
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: ac74d9dd-3125-442a-a7c1-f9e49e05faca
dialer:
type: tcp
客户端的配置与之前一致。
访问端¶
命令行
自动嗅探主机名
gost -L tcp://:8000?sniffing=true -F tunnel://:8443?tunnel.id=ac74d9dd-3125-442a-a7c1-f9e49e05faca
或指定主机名
gost -L tcp://:8000/srv-2.local -F tunnel://:8443?tunnel.id=ac74d9dd-3125-442a-a7c1-f9e49e05faca
配置文件
services:
- name: service-0
addr: :8000
handler:
type: tcp
chain: chain-0
metadata:
sniffing: true
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: ac74d9dd-3125-442a-a7c1-f9e49e05faca
dialer:
type: tcp
访问端开启私有入口服务监听在8000端口,通过设置tunnel.id选项指定所要使用的隧道。
TCP服务¶
隧道并不限于Web流量,也可以应用于任何TCP服务(例如SSH)。例如上面服务端的Ingress中ssh.srv-2.local和redis.srv-3.local主机对应的隧道。
Reverse Proxy - TCP Tunnel
客户端¶
services:
- name: service-0
addr: :0
handler:
type: rtcp
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: ssh
addr: 192.168.2.1:22
host: ssh.srv-2.local
- name: redis
addr: 192.168.2.2:6379
host: redis.srv-3.local
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: aede1f6a-762b-45da-b937-b6632356555a
dialer:
type: tcp
客户端的转发器设置了两个目标节点:192.168.2.1:22的ssh服务和192.168.2.2:6379的redis服务。 注意每个节点上的host参数需要与服务端Ingress对应规则中的hostname相匹配。
访问端¶
命令行
SSH服务
gost -L tcp://:2222/ssh.srv-2.local -F tunnel://:8443?tunnel.id=aede1f6a-762b-45da-b937-b6632356555a
或redis服务
gost -L tcp://:6379/redis.srv-3.local -F tunnel://:8443?tunnel.id=aede1f6a-762b-45da-b937-b6632356555a
配置文件
services:
- name: service-0
addr: :2222
handler:
type: tcp
chain: chain-0
listener:
type: tcp
forwarder:
nodes:
- name: ssh
addr: ssh.srv-2.local
# - name: redis
# addr: redis.srv-3.local
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: aede1f6a-762b-45da-b937-b6632356555a
dialer:
type: tcp
访问端需要在转发器中指定目标节点主机名,需要与服务端Ingress对应规则中的hostname相匹配。
UDP服务¶
隧道也可以应用于任何UDP服务(例如DNS)。例如上面服务端的Ingress中dns.srv-2.local和dns.srv-3.local主机对应的隧道。
Reverse Proxy - UDP Tunnel
客户端¶
services:
- name: service-0
addr: :0
handler:
type: rudp
listener:
type: rudp
chain: chain-0
forwarder:
nodes:
- name: dns-1
addr: 192.168.2.1:53
host: dns.srv-2.local
- name: dns-2
addr: 192.168.2.2:53
host: dns.srv-3.local
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: aede1f6a-762b-45da-b937-b6632356555a
dialer:
type: tcp
客户端的转发器设置了两个目标节点:192.168.2.1:53的DNS服务和192.168.2.2:53的DNS服务。 注意每个节点上的host参数需要与服务端Ingress对应规则中的hostname相匹配。
访问端¶
命令行
gost -L udp://:1053/dns.srv-2.local -L udp://:2053/dns.srv-3.local -F tunnel://:8443?tunnel.id=aede1f6a-762b-45da-b937-b6632356555a
配置文件
services:
- name: service-0
addr: :1053
handler:
type: udp
chain: chain-0
listener:
type: udp
forwarder:
nodes:
- name: dns-1
addr: dns.srv-2.local
- name: service-1
addr: :2053
handler:
type: udp
chain: chain-0
listener:
type: udp
forwarder:
nodes:
- name: dns-2
addr: dns.srv-3.local
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: aede1f6a-762b-45da-b937-b6632356555a
dialer:
type: tcp
访问端需要在转发器中指定目标节点主机名,需要与服务端Ingress对应规则中的hostname相匹配。
直接路由¶
上面的隧道都是通过定义Ingress,根据Ingress规则中虚拟主机名来路由,这种方式可以看作是间接路由模式,Ingress在这里即是路由表,又可以看作是白名单。
也可以开启直接路由模式,访问端与客户端直接通过隧道ID进行匹配,当访问端未匹配上Ingress中的规则后会采用隧道ID直接匹配方式来查找客户端。Ingress是可选的。
提高安全性
当开启直接路由模式后,隧道的分配及使用完全由客户端控制,请确保服务端仅能够被受信任的用户访问,可以通过增加用户认证功能提高服务的安全性,以防止被滥用。
服务端通过tunnel.direct选项开启直接路由模式。
命令行
gost -L tunnel://:8443?tunnel.direct=true
配置文件
services:
- name: service-0
addr: :8443
handler:
type: tunnel
metadata:
tunnel.direct: true
listener:
type: tcp
多路复用¶
隧道本身支持多路复用,单个隧道不仅限于某一种类型的流量使用,也支持同时传输不同类型的流量(Web,TCP,UDP)。
TCP和UDP服务可以共用同一个隧道,隧道会对TCP和UDP的客户端连接作区分,对于TCP的访问端仅会匹配TCP客户端,对于UDP的访问端仅会区配UDP客户端。
下面将通过一个具体的示例来说明。
示例 - 通过隧道进行iperf测试¶
Reverse Proxy - iperf3
服务端¶
命令行
Ingress模式
gost -L tunnel://:8443?tunnel=iperf.local:22f43305-42f7-4232-bbbc-aa6c042e3bc3
或直接路由模式
gost -L tunnel://:8443?tunnel.direct=true
配置文件
services:
- name: service-0
addr: :8443
handler:
type: tunnel
metadata:
ingress: ingress-0
# direct routing mode
# tunnel.direct: true
listener:
type: tcp
ingresses:
- name: ingress-0
rules:
- hostname: "iperf.local"
endpoint: 22f43305-42f7-4232-bbbc-aa6c042e3bc3
客户端¶
由于转发的目标只有一个,因此可以使用命令行直接转发,如果要转发多个服务需要通过配置文件在转发器中为每个目标节点定义主机名(forwarder.nodes.host),通过主机名来匹配不同的服务。
命令行
gost -L rtcp://:0/:5201 -L rudp://:0/:5201 -F tunnel://:8443?tunnel.id=22f43305-42f7-4232-bbbc-aa6c042e3bc3
配置文件
services:
- name: iperf-tcp
addr: :0
handler:
type: rtcp
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: iperf
addr: :5201
host: iperf.local
- name: iperf-udp
addr: :0
handler:
type: rudp
listener:
type: rudp
chain: chain-0
forwarder:
nodes:
- name: iperf
addr: :5201
host: iperf.local
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: 22f43305-42f7-4232-bbbc-aa6c042e3bc3
dialer:
type: tcp
访问端¶
转发的目标地址需要与服务端的Ingress中规则对应的主机名匹配,如果要转发多个服务需要通过配置文件在转发器中为每个目标节点定义主机名(forwarder.nodes.host),通过主机名来匹配不同的服务。
UDP连接保持
UDP端口转发服务默认在进行完一次数据交互后连接状态便失效,这对于像DNS这种服务会很有效。但是对于需要多次数据交互的UDP服务,需要通过keepalive选项开启连接保持功能,另外可以通过ttl选项来控制超时时长,默认超过5秒无数据交互连接状态将会失效。
命令行
Ingress模式
gost -L tcp://:15201/iperf.local -L udp://:15201/iperf.local?keepalive=true -F tunnel://:8443?tunnel.id=22f43305-42f7-4232-bbbc-aa6c042e3bc3
直接路由模式
gost -L tcp://:15201 -L udp://:15201?keepalive=true -F tunnel://:8443?tunnel.id=22f43305-42f7-4232-bbbc-aa6c042e3bc3
配置文件
services:
- name: iperf-tcp
addr: :15201
handler:
type: tcp
chain: chain-0
listener:
type: tcp
forwarder:
nodes:
- name: iperf
addr: iperf.local
services:
- name: iperf-udp
addr: :15201
handler:
type: udp
chain: chain-0
listener:
type: udp
metadata:
keepalive: true
# ttl: 5s
forwarder:
nodes:
- name: iperf
addr: iperf.local
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: :8443
connector:
type: tunnel
metadata:
tunnel.id: 22f43305-42f7-4232-bbbc-aa6c042e3bc3
dialer:
type: tcp
iperf3服务¶
启动iperf3服务。
iperf3 -s
执行iperf3测试¶
TCP测试
iperf3 -c 127.0.0.1 -p 15201
UDP测试
iperf3 -c 127.0.0.1 -p 15201 -u
公共反向代理服务¶
如果需要临时来反向代理内网服务提供公网访问,可以通过GOST.PLUS提供的公共反向代理服务将内网服务匿名暴露到公网来访问。
gost -L rtcp://:0/192.168.1.1:80 -F tunnel+wss://tunnel.gost.plus:443
或者手动指定隧道ID:
gost -L rtcp://:0/192.168.1.1:80 -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=893787fd-fcd2-46a0-8dd4-f9103ae84df4
当正常连接到GOST.PLUS服务后,会有类似如下日志信息:
{"connector":"tunnel","dialer":"wss","endpoint":"134c714b65d54a4f","hop":"hop-0","kind":"connector","level":"info",
"msg":"create tunnel on 134c714b65d54a4f:0/tcp OK, tunnel=893787fd-fcd2-46a0-8dd4-f9103ae84df4, connector=3464af8b-49c5-424c-89ea-b4e9af075a7d",
"node":"node-0","time":"2023-10-19T23:17:27.403+08:00",
"tunnel":"893787fd-fcd2-46a0-8dd4-f9103ae84df4"}
日志的endpoint信息中134c714b65d54a4f是为此服务生成的临时公共访问点,有效期为1小时。
如果192.168.1.1:80是一个HTTP服务,通过https://134c714b65d54a4f.gost.plus便能立即访问。
TCP服务¶
对于TCP服务同样可以以私有隧道的方式来访问。这里假设192.168.1.1:22是一个SSH服务。
gost -L rtcp://:0/192.168.1.1:22 -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=f8baa731-4057-4300-ab75-c4e603834f1b
内网服务不会在服务端暴露公开端口,需要在访问端开启一个私有入口点:
gost -L tcp://:2222/f1bbbb4aa9d9868a.gost.plus -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=f8baa731-4057-4300-ab75-c4e603834f1b
注意两端的隧道ID必须匹配才能访问到隧道对应的服务。
此时在访问端执行以下命令便可以访问到192.168.1.1:22。
ssh -p 2222 user@localhost
UDP服务¶
同样也可以以私有隧道的方式暴露UDP服务。这里假设192.168.1.1:53是一个DNS服务。
gost -L rudp://:0/192.168.1.1:53 -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=f8baa731-4057-4300-ab75-c4e603834f1b
要访问此服务需要在访问端开启一个私有入口点:
gost -L udp://:1053/f1bbbb4aa9d9868a.gost.plus -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=f8baa731-4057-4300-ab75-c4e603834f1b
注意两端的隧道ID必须匹配才能访问到隧道对应的服务。
此时在访问端执行以下命令便可以访问到192.168.1.1:53。
dig -p 1053 @127.0.0.1
-----------------------------------------------------------
反向代理隧道-高可用¶
在上一篇反向代理隧道教程中,详细的讲述了反向代理隧道的功能和使用方法。在本篇教程中将侧重于服务的部署及系统的高可用性方面。
单点故障¶
一个反向代理隧道系统是由三个部分组成:
服务端 - 反向代理隧道服务,负责隧道的管理和流量的路由。
客户端 - 与服务端建立隧道连接,接收服务端过来的流量,再次路由并转发到目标主机。
访问端 - 访问端通过入口点将请求转发给服务,服务再将流量路由到对应隧道的客户端,最终到达目标主机。
Tunnel
在上面这个系统中存在单点故障(SPOF)问题,当三个部分中的任意一个出现问题,隧道就不可用。例如下图中,当客户端网络出现问题无法与服务端建立隧道连接,或者访问点无法连通服务,其对应的隧道也就无法访问。
Tunnel SPOF
解决单点故障比较成熟的方案是,让系统的每个部分都可以做到水平扩展。通过运行多个实例形成一个集群,当集群中的单个实例出现故障时,其他实例可以继续运作,从而实现整个系统的高可用。对于客户端和访问端的单点问题,可以简单的通过运行多个实例来解决。
Tunnel HA
反向代理隧道中的单个隧道支持多个连接,通过运行多个客户端并指定相同的隧道ID。多个连接在隧道服务端构成一个连接池,服务端以轮询的方式使用这些连接,当检测到客户端的连接异常后会将此连接剔除连接池。访问端也可以通过运行多个访问点来提高可用性。
客户端和访问端是无状态的,因此可以很容易实现水平扩展。但是服务端却无法简单的做到,服务端需要维护每个隧道的状态,隧道本身并不能随着服务端的扩展而自动迁移或复制。
Tunnel SPOF
如上图运行了两个服务端实例,客户端连接到Server-1。此时如果访问端的请求发送到Server-2,由于Server-2中没有隧道的连接,因此路由失败。对于服务端需要一些额外的手段来实现扩展性。
服务注册和发现¶
服务端无法做到水平扩展的原因是,服务端实例之间是相互独立的,彼此无法感知到其他实例中隧道的信息。因此我们需要一种方法来让服务端共享所有的客户端隧道和连接信息。反向代理隧道服务中通过服务注册和发现机制来达到此目的,但其内部并没有集成具体的服务注册和发现功能模块,而是通过插件的方式将功能开放出来,由用户自己选择实现方式。
Tunnel SD
当客户端连接到隧道服务后,服务端会将此客户端的连接信息发送给插件(Register),服务端会定期检查连接状态并向插件报告(Renew)以便维持连接信息的有效性。当客户端断开后,服务端也会报告插件(Deregister)。
当访问端的请求到达服务端后,服务端首先在其自身的连接池中获取隧道的连接,如果没有找到则会再次向插件查询(Get),插件会返回对应隧道的连接列表。其中每个连接信息中包含此连接所在的服务节点地址(入口点),服务端最终将请求转发给其他实例处理。
云原生部署示例¶
当系统的所有部分都可以水平扩展后,就可以借助于Kubernetes等云原生平台来灵活部署。下面是一个完整的高可用反向代理隧道系统部署示例,其中Ingress路由和服务发现的插件部分均采用redis服务提供支持。
客户端通过gost.local域名连接隧道服务:
gost -L file://:8000 -L rtcp://:0/:8000 -F tunnel+ws://gost.local:80?tunnel.id=381433e1-7980-11ee-bbdb-60f262c1e32d
然后就可以通过http://b7de88a94729b931.gost.local来访问。
deploy.yaml
-----------------------------------------------------------
HTTP文件服务¶
HTTP文件服务,将本地的文件系统目录转成HTTP服务。
使用方法¶
命令行
gost -L file://:8080?dir=/path/to/dir
配置文件
services:
- name: service-0
addr: :8080
handler:
type: file
metadata:
dir: /path/to/dir
listener:
type: tcp
dir (string):
文件目录,默认为当前工作目录。
转发链
文件服务会忽略转发链。
示例¶
简单的HTTP文件服务¶
将/home以HTTP服务的方式暴露在8080端口。
命令行
gost -L file://:8080?dir=/home
配置文件
services:
- name: service-0
addr: :8080
handler:
type: file
metadata:
dir: /home
listener:
type: tcp
认证¶
为服务设置基本认证。
命令行
gost -L file://user:pass@:8080
配置文件
services:
- name: service-0
addr: :8080
handler:
type: file
auth:
username: user
password: pass
listener:
type: tcp
TLS¶
为服务增加TLS加密传输层(HTTPS)。
命令行
gost -L file+tls://:8443
配置文件
services:
- name: service-0
addr: :8443
handler:
type: file
listener:
type: tls
公网临时访问¶
如果需要临时通过公网来访问文件服务,可以通过GOST.PLUS提供的公共反向代理服务将本地文件服务匿名暴露到公网来访问。
gost -L file://:8080 -L rtcp://:0/:8080 -F tunnel+wss://tunnel.gost.plus:443
当正常连接到GOST.PLUS服务后,会有类似如下日志信息:
{"connector":"tunnel","dialer":"wss","endpoint":"006478add9ed096a","hop":"hop-0","kind":"connector","level":"info",
"msg":"create tunnel on 006478add9ed096a:0/tcp OK, tunnel=50ce9728-5d92-4d45-871d-4f275d5179cb, connector=956fcbe5-6e2d-439a-8aa3-af0df848a81a",
"node":"node-0","time":"2023-10-19T22:41:05.759+08:00",
"tunnel":"50ce9728-5d92-4d45-871d-4f275d5179cb"}
日志的endpoint信息中006478add9ed096a是为此服务生成的临时公共访问点,有效期为1小时。通过https://006478add9ed096a.gost.plus便能立即访问到此文件服务。
-----------------------------------------------------------
GO Simple Tunnel
GO语言实现的安全隧道
功能特性
多端口监听
多级转发链
多协议支持
TCP/UDP端口转发
TCP/UDP透明代理
DNS解析和代理
TUN/TAP设备
反向代理
负载均衡
路由控制
限速限流
准入控制
动态配置
插件系统
Prometheus监控指标
Web API
Web UI
Telegram讨论群:https://t.me/gogost
Google讨论组:https://groups.google.com/d/forum/go-gost
提交Issue:https://github.com/go-gost/gost/issues
旧版入口:v2.gost.run
下载安装
二进制文件
https://github.com/go-gost/gost/releases
源码编译
git clone https://github.com/go-gost/gost.git
cd gost/cmd/gost
go build
Docker
docker run --rm gogost/gost -V
Shadowsocks Android插件
xausky/ShadowsocksGostPlugin
https://github.com/xausky/ShadowsocksGostPlugin
发表评论: