你的位置:首页 > 互联网IT
gost,gost3,gost-v3,gost3配置文件教材,http代理,socks5代理,转发端口,shadowsocks代理,SS代理,负载均衡,中转服务,端口映射,gost3命令教材,GOST
gost,gost3,gost-v3,gost3配置文件教材,http代理,socks5代理,转发端口,shadowsocks代理,SS代理,负载均衡,中转服务,端口映射,gost3命令教材,GOST.PLUS-公共反向代理服务,串口重定向,反向代理隧道实战
系统: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
本文内容:GOST.PLUS-公共反向代理服务,串口重定向,反向代理隧道实战,反向代理与内网穿透,利用Traefik和Docker部署GOST服务,基于TUN设备的VPN组网,流量控制-分流器,GOST v3动态分流功能的一种实现方式
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
-----------------------------------------------------------
GOST.PLUS-公共反向代理服务
ginuerzh · 2023-10-15 22:00 · 10min read
反向代理隧道是GOST中新增的一个较大功能,同时也是一个很重要的功能,借助于反向代理和内网穿透,可以很方便的将内网Web服务暴露到公网,随时随地都能访问。
为了能够对此功能进行更全面的测试,同时也为了能够给需要临时暴露内网服务的用户提供一种快捷的方式,特公开推出GOST.PLUS公共反向代理测试服务。此服务面向所有用户开放,无需注册。
本服务以测试为主要目的,所有公共访问点均为临时访问点,有效期为1小时。
使用方法¶
假如本地有一个HTTP服务192.168.1.1:80需要临时暴露到公网,只需在本地机器上运行以下命令:
gost -L rtcp://:0/192.168.1.1:80 -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=f8baa731-4057-4300-ab75-c4e603834f1b
或者使用随机生成的隧道ID(不设置tunnel.id选项):
gost -L rtcp://:0/192.168.1.1:80 -F tunnel+wss://tunnel.gost.plus:443
隧道ID
每个隧道通过tunnel.id指定的隧道ID来唯一标识,每个隧道ID对应唯一的一个公共访问点。隧道ID是一个合法的UUID,可以通过UUID生成器来生成。
Caution
隧道ID作为隧道和服务的唯一凭证,请妥善保管,防止泄露被滥用。
执行后如果隧道建立成功则会有以下日志输出:
{"connector":"tunnel","dialer":"wss","endpoint":"f1bbbb4aa9d9868a","hop":"hop-0","kind":"connector","level":"info",
"msg":"create tunnel on f1bbbb4aa9d9868a:0/tcp OK, tunnel=f8baa731-4057-4300-ab75-c4e603834f1b, connector=df4d62df-8b73-478a-96a2-26826e9cd675",
"node":"node-0","time":"2023-10-15T14:21:29.580Z",
"tunnel":"f8baa731-4057-4300-ab75-c4e603834f1b"}
日志的endpoint字段中f1bbbb4aa9d9868a即为此服务的公共访问点,此时通过https://f1bbbb4aa9d9868a.gost.plus便可访问到内网的192.168.1.1:80服务。
自定义公共访问点¶
除了自动生成公共访问点,也可以通过自己指定访问点名称:
gost -L rtcp://hello/192.168.1.1:80 -F tunnel+wss://tunnel.gost.plus:443?tunnel.id=f8baa731-4057-4300-ab75-c4e603834f1b
上面的命令中指定了公共访问点为test,便可以通过https://hello.gost.plus来访问。
绑定访问点
每个访问点在第一次使用时会注册并绑定到对应的隧道ID,绑定时长为1小时,在此期间其他隧道无法再次绑定并使用此访问点。当超时后绑定将失效,访问点可以再次绑定到不同的隧道。
更多的设置和使用方法请参考反向代理。
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
自建公共反向代理¶
你也可以通过以下配置来搭建自己的反向代理服务。
gost.yml
services:
- name: service-0
addr: :8080
handler:
type: tunnel
metadata:
entrypoint: :8000
ingress: ingress-0
listener:
type: ws
ingresses:
- name: ingress-0
plugin:
type: grpc
addr: gost-plugins:8000
log:
level: info
docker-compose.yml
version: '3'
services:
traefik:
image: traefik:v2.9.6
restart: always
command:
# - "--api.insecure=true"
# - "--api.dashboard=true"
- "--providers.docker"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--log.level=INFO"
- "--log.format=json"
# - "--accesslog"
# - "--accesslog.format=json"
# - "--accesslog.filters.statuscodes=400-600"
# - "--serversTransport.maxIdleConnsPerHost=0"
# - "--serversTransport.forwardingTimeouts.idleConnTimeout=1s"
ports:
# The HTTP port
- "80:80"
# The HTTPS port
- "443:443"
# The Web UI (enabled by --api.insecure=true)
# - "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- "/var/run/docker.sock:/var/run/docker.sock:ro"
gost-tunnel:
image: gogost/gost
restart: always
labels:
- "traefik.http.routers.gost-tunnel.tls=true"
- "traefik.http.routers.gost-tunnel.rule=Host(`tunnel.gost.local`)"
- "traefik.http.routers.gost-tunnel.service=gost-tunnel"
- "traefik.http.services.gost-tunnel.loadbalancer.server.port=8080"
- "traefik.http.routers.gost-ingress.tls=true"
- "traefik.http.routers.gost-ingress.service=gost-ingress"
- "traefik.http.routers.gost-ingress.rule=HostRegexp(`{subdomain:[a-z0-9]+}.gost.local`)"
- "traefik.http.routers.gost-ingress.priority=10"
- "traefik.http.services.gost-ingress.loadbalancer.server.port=8000"
volumes:
- ./gost.yaml:/etc/gost/gost.yaml
gost-plugins:
image: ginuerzh/gost-plugins
restart: always
command: "ingress --addr=:8000 --redis.addr=redis:6379 --redis.db=2 --redis.expiration=1h --domain=gost.local --log.level=debug"
redis:
image: redis:7.2.1-alpine
restart: always
command: "redis-server --save 60 1 --loglevel warning"
volumes:
- redis:/data
volumes:
redis:
driver: local
-----------------------------------------------------------
串口重定向
ginuerzh · 2023-10-13 23:00 · 15min read
串口目前在个人电脑主机上基本不存在了,但在一些小型设备特别是工业设备和工控机上还是能够看到这些接口。由于串口通信的方式和我们平时所使用的TCP/IP有很大差异,因此在调试和分析基于串口的通讯协议时所用的方法也会有所不同。
GOST在3.0.0-rc8之后的版本中增加了串口重定向或者也可以称做串口端口转发功能,可以将本地串口数据转发给TCP服务,或者将TCP服务的数据转发给本地串口,也可以将本地串口转发到远程主机的串口。利用串口转发可以实现两个功能:串口远程通讯和串口通讯数据监控。
虚拟串口
后面需要借助于虚拟串口让软件在不具备物理串口设备的主机上也可以进行串口通信。
Windows可以使用Null-modem emulator来创建虚拟串口。
Linux可以通过以下命令创建类似的虚拟串口:
socat -d -d pty,raw,echo=0 pty,raw,echo=0
串口远程通讯¶
串口的通讯是点对点的物理直连,没有网络的概念,因此需要设备在旁边时刻连着对端,这是物理空间上的一个局限性。通过串口转发可以做到像访问互联网服务一样来访问串口。这里有两种做法,一种是转发到TCP服务,另一种是转发到远程的串口设备。
转发到TCP服务¶
由于串口数据的传输方式和TCP协议类似,也可以看作是流式传输,因此可以将串口数据转发到一个TCP服务,这样就相当于将串口通信转换成了网络通讯。
gost -L serial://COM1 -F tcp://192.168.1.1:8080
转发到远程串口设备¶
如果一个软件需要通过串口与设备通信,正常的做法是在一台有串口的主机上安装软件,将设备通过串口线与此主机相连接,软件打开本地的串口设备,Windows下一般是COM口,例如COM1,COM2。Linux下一般是/dev/ttyS*,例如/dev/ttyS0,/dev/ttyS1,如果是通过USB转串口,一般是/dev/ttyUSB0。
但有些时候设备可能不在身边,或者设备无法移动,这个时候可以利用串口转发将设备所连接的主机上的串口转发到远程任意一台主机上,实现远程通讯。借助于虚拟串口工具,远程主机可以不具备物理串口。
假设设备所连接的主机A地址为192.168.1.1,主机A上的串口为COM1。远程的一台主机B地址为192.168.1.2,主机B上已经通过虚拟串口工具虚拟出两个串口设备COM1和COM2,我们想要主机B上的软件通过虚拟串口COM2与设备进行通信。
首先需要在主机A上开启中转服务:
gost -L relay://:8420
然后在主机B上进行串口端口转发,将主机B上的COM1端口映射到主机A的COM1端口:
gost -L serial://COM1/COM1 -F relay://192.168.1.1:8420
此时主机B上的软件通过COM2口所传输的数据会通过relay中转服务,转发到主机A的COM1口,实现了远程串口通信。
串口数据监控¶
对于TCP/IP网络通讯,可以借助于Wireshark,tcpdump等工具进行实时抓包来采集和分析数据,但是这些工具都不支持串口设备。因此对于串口设备一般都需要借助于专用的调试监控软件来抓取数据。
串口设备还有一个比较特殊的地方,一个端口同时只能被一个进程所占用,这就给抓取数据又增加了一定的难度。如果想抓取并监控软件与设备之间的正常通讯数据,常规手段就不可行了,目前仅找到Serial Port Monitor这一款软件可以做到对被占用的串口设备进行数据监控。
直接的监控不可行,可以通过串口转发来间接达到目的。同样需要借助于虚拟串口,假设主机A上有一个物理串口COM1与设备连接,虚拟串口为COM3和COM4,此时可以让软件使用COM4端口,并将COM1转发到COM3,在转发的过程中就可以抓取数据进行监控。
services:
- name: service-0
addr: COM1
recorders:
- name: recorder-0
record: recorder.service.handler.serial
metadata:
direction: true
timestampFormat: '2006-01-02 15:04:05.000'
hexdump: true
handler:
type: serial
listener:
type: serial
forwarder:
nodes:
- name: target-0
addr: COM3
recorders:
- name: recorder-0
file:
path: 'C:\\serial.data'
这里在端口转发时使用记录器将通信数据记录到文件C:\serial.data当中。最终的数据记录格式如下:
>2023-09-18 10:16:25.117
00000000 60 02 a0 01 70 02 b0 01 c0 01 c0 01 40 02 30 01 |`...p.......@.0.|
00000010 e0 00 30 01 50 02 60 01 40 01 30 01 10 02 f0 00 |..0.P.`.@.0.....|
00000020 20 01 60 01 b0 01 f0 00 10 01 f0 00 c0 01 a0 01 | .`.............|
00000030 40 02 b0 01 10 02 60 02 00 00 00 01 50 01 70 01 |@.....`.....P.p.|
00000040 a0 01 30 01 e0 00 e0 01 40 01 00 01 e0 00 c0 01 |..0.....@.......|
00000050 40 01 e0 00 f0 00 20 02 50 01 10 02 10 01 10 02 |@..... .P.......|
00000060 80 01 20 02 30 01 10 02 30 01 00 01 20 01 10 02 |.. .0...0... ...|
<2023-09-18 10:16:25.120
00000000 d0 00 d0 00 10 01 10 02 50 01 e0 00 00 01 d0 01 |........P.......|
00000010 f0 00 10 01 c0 01 40 02 80 01 00 01 20 |......@..... |
>表示源端口发出的数据(COM1 > COM3),<表示源端口接收到的数据(COM1 < COM3)。
-----------------------------------------------------------
反向代理隧道实战
ginuerzh · 2023-02-12 23:00 · 15min read
上一篇博文中,对反向代理和内网穿透做了基本的介绍。本篇将通过具体应用案例更加直观的展示反向代理隧道的使用。
反向代理隧道是将反向代理和内网穿透两个功能相结合一种技术手段,这两个概念之间其实没有必然的联系,反向代理可以不使用内网穿透,内网穿透也并不一定是为了实现反向代理,只不过很多情况下我们需要这两个功能组合在一起使用。例如一般的家庭网络或公司网络可能没有公网IP,因此无法通过公网直接访问,这个时候就需要用到内网穿透,通过一台具有公网IP的机器来间接的访问内网的服务。
假设有一台公网服务器并且绑定了域名my.domain。我们想要通过域名router.my.domain来访问到家庭网络中的路由器(192.168.1.1:80),并想要通过域名work.my.domain来访问公司中的项目管理平台(172.10.1.1:80)。
服务端¶
这里使用Docker Compose来简化部署,并且使用Traefik作为前置代理,通过域名将流量路由到隧道服务。
隧道服务监听在8080端口采用websocket传输方式并通过域名tunnel.my.domain来访问。router.my.domain和work.my.domain的流量通过traefik路由到了公共入口点(entrypoint)8000端口。
服务端定义了两条隧道:
router.my.domain对应隧道6c538042-cc24-4910-8887-0f50916ad97f将连接到家庭网络。
work.my.domain对应隧道68e15803-a287-4ebd-b2ac-1aee1aa733ca将连接到公司网络。
docker-compose.yaml
version: '3'
services:
traefik:
image: traefik:v2.9.6
restart: always
command:
- "--providers.docker"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
ports:
# The HTTP port
- "80:80"
# The HTTPS port
- "443:443"
volumes:
# So that Traefik can listen to the Docker events
- "/var/run/docker.sock:/var/run/docker.sock:ro"
gost-tunnel:
image: gogost/gost:3.0.0-rc10
command: "-L tunnel+ws://:8080?entrypoint=:8000&tunnel=router.my.domain:6c538042-cc24-4910-8887-0f50916ad97f,work.my.domain:68e15803-a287-4ebd-b2ac-1aee1aa733ca"
restart: always
labels:
- "traefik.http.routers.gost-tunnel.tls=true"
- "traefik.http.routers.gost-tunnel.rule=Host(`tunnel.my.domain`)"
- "traefik.http.routers.gost-tunnel.service=gost-tunnel"
- "traefik.http.services.gost-tunnel.loadbalancer.server.port=8080"
- "traefik.http.routers.gost-ingress.tls=true"
- "traefik.http.routers.gost-ingress.rule=Host(`router.my.domain`, `work.my.domain`)"
- "traefik.http.routers.gost-ingress.service=gost-ingress"
- "traefik.http.services.gost-ingress.loadbalancer.server.port=8000"
客户端¶
在家庭网络的一台机器上运行以下命令建立到服务端的隧道
gost -L rtcp://:0/192.168.1.1:80 -F tunnel+wss://tunnel.my.domain:443?tunnel.id=6c538042-cc24-4910-8887-0f50916ad97f
在公司网络的一台机器上运行以下命令建立到服务端的隧道
gost -L rtcp://:0/172.10.1.1:80 -F tunnel+wss://tunnel.my.domain:443?tunnel.id=68e15803-a287-4ebd-b2ac-1aee1aa733ca
如果家庭或公司内的服务需要通过域名来访问(例如家庭内部需要通过router.my.home来访问路由器)可以做如下设置
services:
- name: service-0
addr: :0
handler:
type: rtcp
metadata:
sniffing: true
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: router
addr: 192.168.1.1:80
# host: router.my.domain
http:
host: router.my.home
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: tunnel.my.domain:443
connector:
type: tunnel
metadata:
tunnel.id: 6c538042-cc24-4910-8887-0f50916ad97f
dialer:
type: wss
以上设置完毕后,就可以通过router.my.domain来访问到家庭路由器,通过work.my.domain访问到公司项目管理平台。
-----------------------------------------------------------
反向代理与内网穿透
ginuerzh · 2023-01-16 22:00 · 30min read
反向代理也是代理服务的一种,我们通常使用的代理服务,例如HTTP/SOCKS5代理,其代理的目标是客户端,代理服务代替客户端与所访问的服务器建立连接,而反向代理服务代理的目标是服务器,因此像HTTP/SOCKS5这种代理服务也被称作正向代理。二者的主要却别在于正向代理中客户端是知道代理服务的存在,而反向代理中客户端(甚至是服务端)是不知道代理服务的存在,在客户端看来代理服务就是我真正要访问的服务。
从某种角度来看,反向代理与端口转发是一样的,二者都是在两个端口之间建立映射关系,将数据从一个端口转发到另外一个端口,只不过反向代理会利用转发的数据进行更精确的控制,而端口转发一般不会依赖于数据的内容,仅仅是纯粹的端到端的转发行为。GOST中的反向代理就是基于端口转发来实现的。
GOST从v2.1版本开始就已经实现了端口转发的功能,其间这个功能一直没有多大的变化,直到v3.0.0-rc.1版本,为了实现反向代理的功能而对端口转发进行了扩展。
反向代理¶
GOST中的端口转发原本是不会对转发的数据进行解析,而反向代理特别是针对Web服务的反向代理,一般需要我们根据所要访问的主机名(或域名)来对流量进行路由,这个主机名就需要从所要转发的数据中获取,如果是HTTP流量对应的是HTTP头部的Host字段,如果是HTTPS流量对应的是TLS握手协议中的SNI信息。
Reverse Proxy - TCP Port Forwarding
GOST中端口转发服务开启流量嗅探(sniffing选项)后便能够对数据进行进一步解析获取所要访问的目标主机名,再与转发器中定义的目标服务进行主机名匹配找到最终要转发到的目标服务。此时的端口转发更像是一个SNI代理,区别在于SNI代理更像是一个正向代理,对其所转发的目标主机一般不会有太多限制,而反向代理中的目标主机一般是预定义的一组服务。
services:
- name: service-0
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
curl --resolve example.com:80:127.0.0.1 http://example.com
这里反向代理可以看作是目标主机(example.com)的镜像,用户访问代理服务与访问目标主机没有什么区别。
内网穿透¶
上面所说的反向代理能够工作的一个前置条件是反向代理能够直接访问到目标主机,如果目标主机处于内网且没有公网IP,以上方式就无效了。这种情况就需要进行内网穿透,让内网的主机主动与具有公网IP的主机建立一个连接,当数据发送给具有公网IP的主机后,再通过这个连接转发给内网中的目标主机。
Reverse Proxy - Remote TCP Port Forwarding
GOST中的远程端口转发正是做这件事的,因此远程端口转发也同样支持了对流量进行嗅探,并能够根据主机名来路由流量。
services:
- name: http
addr: :80
handler:
type: rtcp
metadata:
sniffing: true
listener:
type: rtcp
chain: chain-0
forwarder:
nodes:
- name: srv-0
addr: 192.168.1.1:80
host: srv-0.local
- name: srv-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: tunnel
dialer:
type: tcp
curl --resolve srv-1.local:80:SERVER_IP http://srv-1.local
内网穿透-加强版¶
以上的内容已经基本上实现了一个简单的反向代理服务,但是针对需要内网穿透的Web服务反向代理还有不足之处。一般的Web反向代理(例如Nginx,Traefik)对外只会暴露固定的几个预定义的端口作为入口(例如80,443),并且入口点流量的路由控制权应当是在服务端。而以上的远程端口转发,入口和路由的定义都是在客户端,这样对于整个服务来说不可控。
Reverse Proxy - Remote TCP Port Forwarding
GOST在v3.0.0-rc.3版本中通过对Relay协议的扩展,增强了内网穿透的功能,使其能够更好的适配反向代理。
服务端¶
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
客户端¶
services:
- name: service-0
addr: :0
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: tunnel
metadata:
tunnel.id: 4d21094e-b74c-4916-86c1-d9fa36ea677b
dialer:
type: tcp
入口点(EntryPoint)¶
入口点指定了流量的入口,所有用户的流量统一由入口点进入。当设定了入口点后处理器内部会创建一个监听在入口点的服务,用户的流量到达入口点后,此服务内部会对流量进行嗅探,获取请求的目标主机,再对流量做相应的路由。
隧道(Tunnel)¶
隧道是内网穿透中客户端与服务端之间建立的(逻辑上的)通道,每个隧道都有一个唯一ID(合法的UUID),一个隧道可以有多个连接,当多个客户端使用相同的隧道ID建立连接时,这些连接被归属于同一个隧道。服务端会从隧道的多个连接中选择一个可用的连接进行数据转发。
Ingress¶
Ingress定义了入口点进入的流量的路由规则,每个规则是主机名到隧道的映射,例如访问srv-0.local和srv-1.local的流量都会被路由到隧道4d21094e-b74c-4916-86c1-d9fa36ea677b,访问srv-2.local的流量会被路由到隧道ac74d9dd-3125-442a-a7c1-f9e49e05faca。
隧道ID分配
隧道的ID应当由服务端提前分配并记录在Ingress中,如果客户端使用了一个未在Ingress中注册的隧道ID,则流量无法路由到此客户端。
加密¶
隧道依赖于Relay协议,Relay协议本身不具备数据加密的功能,可以通过与各种具有加密功能的数据通道例如TLS,gRPC,QUIC等组合使用来对整个隧道进行加密。
-----------------------------------------------------------
利用Traefik和Docker部署GOST服务
ginuerzh · 2022-12-20 22:00 · 15min read
Traefik是类似于Nginx的反向代理工具,其云原生的特性使其在Docker和Kubernetes环境下使用起来非常方便。
这里假设你的域名为gost.run,每个服务使用单独的子域名来路由,也可以使用URI路径来路由。
Docker¶
由于Traefik和GOST都支持Docker容器化,因此这里直接采用Docker Compose来进一步简化部署流程。
docker-compose.yaml
version: '3'
services:
traefik:
# The official v2 Traefik docker image
image: traefik:v2.9.6
restart: always
# Enables the web UI and tells Traefik to listen to docker
command:
- "--providers.docker"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
# - "--api.insecure=true"
# - "--api.dashboard=true"
# - "--log.level=INFO"
# - "--log.format=json"
# - "--accesslog"
# - "--accesslog.format=json"
# - "--accesslog.filters.statuscodes=400-600"
ports:
# The HTTP port
- "80:80"
# The HTTPS port
- "443:443"
# The Web UI (enabled by --api.insecure=true)
# - "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- "/var/run/docker.sock:/var/run/docker.sock:ro"
labels:
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.gost.run`)"
- "traefik.http.services.dashboard.loadbalancer.server.port=8080"
gost-ws:
image: gogost/gost
restart: always
command: "-L relay+ws://:8080"
labels:
- "traefik.http.routers.gost-ws.tls=true"
- "traefik.http.routers.gost-ws.rule=Host(`ws.gost.run`)"
- "traefik.http.services.gost-ws.loadbalancer.server.port=8080"
gost-grpc:
image: gogost/gost
restart: always
command: "-L relay+grpc://:8080?grpcInsecure=true"
labels:
- "traefik.http.routers.gost-grpc.tls=true"
- "traefik.http.routers.gost-grpc.rule=Host(`grpc.gost.run`)"
- "traefik.http.services.gost-grpc.loadbalancer.server.port=8080"
- "traefik.http.services.gost-grpc.loadbalancer.server.scheme=h2c"
gost-pht:
image: gogost/gost
restart: always
command: "-L relay+pht://:8080"
labels:
- "traefik.http.routers.gost-pht.tls=true"
- "traefik.http.routers.gost-pht.rule=Host(`pht.gost.run`)"
- "traefik.http.services.gost-pht.loadbalancer.server.port=8080"
watchtower:
image: containrrr/watchtower:1.5.1
restart: always
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
command: --interval 300
执行以下命令就可以一键部署完成:
docker-compose -f docker-compose.yml -p web up -d
以下为配置文件的详细说明。
Traefik¶
traefik服务暴露80和443端口作为访问入口,并且将80端口重定向到443端口。
Traefik自带的有dashboard,可以通过--api.insecure=true和--api.dashboard=true选项开启,并通过相应的labels配置路由,这里通过traefik.gost.run来访问。
GOST Websocket¶
gost-ws服务是一个采用Websocket作为数据通道的relay代理服务,监听在8080端口,通过ws.gost.run子域名进行路由。
这里之所以没有使用TLS加密的Websocket数据通道(wss),是因为Traefik服务已经自动处理了。
另外服务的端口无需暴露出来即可访问。
GOST gRPC¶
gost-grpc服务是一个采用gRPC作为数据通道的relay代理服务,监听在8080端口,通过grpc.gost.run子域名进行路由。
与gost-ws服务类似,这里使用grpcInsecure=true选项使用明文传输,将TLS的处理工作交给了Traefik。
注意这里服务上的labels需要增加一项traefik.http.services.gost-grpc.loadbalancer.server.scheme=h2c以表明此服务为gRPC服务。
GOST PHT¶
gost-pht服务是一个采用PHT作为数据通道的relay代理服务,监听在8080端口,通过pht.gost.run子域名进行路由。
Watchtower¶
Watchtower是一个自动更新容器的工具,它会定期检查当前运行的容器镜像是否有更新,并自动拉取新的镜像运行新的容器来替换现有的旧容器。这里也可以不使用此服务。
Kubernetes¶
由于Traefik是k3s默认的Ingress Controller,因此这里就以k3s环境为例,k3s的版本为v1.24.3+k3s1,对应的Traefik版本为v2.6.2(rancher/mirrored-library-traefik:2.6.2)。
deploy.yaml
apiVersion: v1
kind: Service
metadata:
name: gost-ws
spec:
selector:
app: gost-ws
ports:
- name: ws
port: 8080
targetPort: ws
---
apiVersion: v1
kind: Service
metadata:
name: gost-grpc
spec:
selector:
app: gost-grpc
ports:
- name: grpc
port: 8080
targetPort: grpc
---
apiVersion: v1
kind: Service
metadata:
name: gost-pht
spec:
selector:
app: gost-pht
ports:
- name: pht
port: 8080
targetPort: pht
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gost-ws
spec:
replicas: 1
selector:
matchLabels:
app: gost-ws
template:
metadata:
name: gost-ws
labels:
app: gost-ws
spec:
containers:
- image: gogost/gost
name: gost
args:
- -L
- relay+ws://:8080
ports:
- name: ws
containerPort: 8080
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gost-grpc
spec:
replicas: 1
selector:
matchLabels:
app: gost-grpc
template:
metadata:
name: gost-grpc
labels:
app: gost-grpc
spec:
containers:
- image: gogost/gost
name: gost
args:
- -L
- relay+grpc://:8080?grpcInsecure=true
ports:
- name: grpc
containerPort: 8080
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gost-pht
spec:
replicas: 1
selector:
matchLabels:
app: gost-pht
template:
metadata:
name: gost-pht
labels:
app: gost-pht
spec:
containers:
- image: gogost/gost
name: gost
args:
- -L
- relay+pht://:8080
ports:
- name: pht
containerPort: 8080
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gost-ws
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/preserve-host: "true"
spec:
rules:
- host: ws.gost.run
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gost-ws
port:
name: ws
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gost-pht
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/preserve-host: "true"
spec:
rules:
- host: pht.gost.run
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gost-pht
port:
name: pht
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gost-grpc
annotations:
kubernetes.io/ingress.class: grpc
spec:
rules:
- host: grpc.gost.run
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gost-grpc
port:
name: grpc
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: gost-grpc
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`grpc.gost.run`)
priority: 11
services:
- name: gost-grpc
passHostHeader: true
port: 8080
weight: 10
scheme: h2c
对于gost-grpc服务,其Ingress需要通过annotation kubernetes.io/ingress.class: grpc指定其Class为grpc,并使用Traefik特有的CRD IngressRoute来定义路由规则。
执行以下命令便可以部署了:
kubectl apply -f deploy.yaml
Cloudflare CDN¶
之所以选择以上三种类型的数据通道,是因为这些通道可以被反向代理服务所代理(Traefik, Nginx),另外这几个通道也可以配合CDN使用,例如Cloudflare,这样既可以使用免费的TLS证书,并让CDN自动管理证书,又可以隐藏自己的服务器地址。
对于Websocket通道,需要在Cloudflare的Network设置界面中启用Websockets协议,默认应该是已经启用。客户端可以通过以下命令建立连接:
gost -L :8080 -F relay+wss://ws.gost.run:443
对于gRPC通道,需要在Cloudflare的Network设置界面中开启gRPC协议。客户端可以通过以下命令建立连接:
gost -L :8080 -F relay+grpc://grpc.gost.run:443
对于PHT通道,可以直接使用,或者使用HTTP/3作为底层传输方式,需要在Cloudflare的Network设置界面中开启HTTP/3加速功能。客户端可以通过以下命令建立连接:
直接连接
gost -L :8080 -F relay+phts://pht.gost.run:443
通过HTTP/3加速
gost -L :8080 -F relay+h3://pht.gost.run:443
如果你没有自己的域名,也是可以通过域名IP映射来访问服务,假设你的服务器IP为192.168.1.2:
gost -L :8080 -F relay+wss://ws.gost.run:443?hosts=ws.gost.run:192.168.1.2
-----------------------------------------------------------
基于TUN设备的VPN组网
ginuerzh · 2022-10-21 22:00 · 30min read
GOST最初是在v2.9版本中引入对TUN(和TAP)设备的支持,在v3版本(beta.4)中又将实现方式由songgao/water库(TAP未变化)改为了wireguard-go,并且增加了心跳和认证机制。
GOST中TUN设备的设计思想是简单轻量,因此没有添加过于复杂的配置,对数据也没有做过多的处理。只要能够满足一些特定的使用场景就达到目的了,如果需要更加复杂的应用完全可以通过wireguard来实现。
TUN设备可以有很多的用处,比较多的可能是用来构建VPN,这里就以讲一下基于GOST的TUN设备VPN组网方案。
VPN组网¶
这个应该是所有VPN方案最常见的应用场景,通过VPN将多个局域网连接在一起互相可以访问。 例如在家可以访问到公司的内部网络或在公司能够访问到家里的网络,或者在外面出差可以同时访问到公司和家里的网络。
GOST中的TUN是客户端-服务器模式,必须要有一个服务器作为中转来连接和路由客户端。因此以上的组网方式需要有一台公网服务器,让家庭网络和公司网络都能够访问到。
这里假如公司网络中的一台机器C1(所在网络为192.168.100.0/24),家庭网络中的一台机器C2(所在网络为192.168.101.0/24)和外面的另外一台机器C3(所在网络为192.168.102.0/24)均可以访问公网的服务器S(所在网络为192.168.1.0/24,公网IP为1.2.3.4)。首先在服务器S上运行TUN服务端(确保服务器的UDP端口8421开放):
services:
- name: tun
addr: :8421
handler:
type: tun
listener:
type: tun
metadata:
net: 192.168.123.1/24
routes:
- "192.168.100.0/24 192.168.123.2"
- "192.168.101.0/24 192.168.123.3"
这里服务器S上TUN设备的IP为192.168.123.1,并配置路由表:
发往192.168.100.0/24网络的数据将转发给192.168.123.2。
发往192.168.101.0/24网络的数据将转发给192.168.123.3。
再分别在C1,C2,C3机器上运行客户端。
客户端C1 - 192.168.123.2¶
命令行
gost -L "tun://:0/1.2.3.4:8421?net=192.168.123.2/24&keepAlive=true&route=192.168.101.0/24"
配置文件
services:
- name: tun
addr: :0
handler:
type: tun
metadata:
keepAlive: true
ttl: 10s
listener:
type: tun
metadata:
net: 192.168.123.2/24
route: 192.168.101.0/24
forwarder:
nodes:
- name: target-0
addr: 1.2.3.4:8421
客户端C2 - 192.168.123.3¶
命令行
gost -L "tun://:0/1.2.3.4:8421?net=192.168.123.3/24&keepAlive=true&route=192.168.100.0/24"
配置文件
services:
- name: tun
addr: :0
handler:
type: tun
metadata:
keepAlive: true
ttl: 10s
listener:
type: tun
metadata:
net: 192.168.123.3/24
route: 192.168.100.0/24
forwarder:
nodes:
- name: target-0
addr: 1.2.3.4:8421
客户端C3 - 192.168.123.4¶
命令行
gost -L "tun://:0/1.2.3.4:8421?net=192.168.123.4/24&keepAlive=true&route=192.168.100.0/24,192.168.101.0/24"
配置文件
services:
- name: tun
addr: :0
handler:
type: tun
metadata:
keepAlive: true
ttl: 10s
listener:
type: tun
metadata:
net: 192.168.123.4/24
route: 192.168.100.0/24,192.168.101.0/24
forwarder:
nodes:
- name: target-0
addr: 1.2.3.4:8421
这里比较关键的是客户端的路由配置(route参数):
在C1上设置路由为家庭网络192.168.101.0/24让C1可以访问到C2所在的网络,
在C2上设置路由为公司网络192.168.100.0/24让C2可以访问到C1所在网络,
在C3上设置路由为公司网络192.168.100.0/24和家庭网络192.168.101.0/24让C3可以同时访问到C1和C2所在的网络。
iptables配置¶
经过以上配置后,各个TUN设备之间可以相互通讯,但要访问彼此所在的网络仅配置路由是不够的,还需要通过iptables来配置IP转发。
iptables -t nat -A POSTROUTING -s 192.168.123.0/24 ! -o tun0 -j MASQUERADE
当客户端添加了以上iptables规则后,此客户端所在的网络才能被其他的客户端访问。
心跳¶
上面的客户端均通过keepAlive参数开启心跳机制,这也是推荐的做法。心跳在这里有两方面的作用:
GOST中TUN客户端和服务端使用UDP协议进行数据传输,通过心跳可以让客户端感知到网络的连通性。当心跳超时后(3个心跳周期时长),客户端会重新初始化连接。
服务端通过维护一个动态客户端映射表来进行客户端之间的数据包路由(客户端的TUN设备IP与客户端的UDP连接IP:PORT映射),服务端通过客户端的心跳更新规则,当服务端重启后表会清除,客户端的心跳会让服务端重新添加到此客户端的映射信息,确保路由正常。
认证¶
以上的配置基本上就可以工作了,但这里面可能会存在一个问题,由于客户端TUN设置的IP是由客户端任意指定,当两个客户端使用同一个IP时就会出现冲突。为了更好的控制客户端的使用,可以在服务端开启认证机制。
services:
- name: tun
addr: :8421
handler:
type: tun
auther: tun
listener:
type: tun
metadata:
net: 192.168.123.1/24
authers:
- name: tun
auths:
- username: 192.168.123.2
password: userpass1
- username: 192.168.123.3
password: userpass2
- username: 192.168.123.4
password: userpass3
服务端通过使用认证器给每个客户端分配TUN设备IP和对应的认证码,这样控制权就交给了服务端,客户端必须使用服务端分配的IP(net参数)和认证码(passphrase参数)才能连接到网络中。
命令行
gost -L "tun://:0/1.2.3.4:8421?net=192.168.123.2/24&keepAlive=true&route=192.168.101.0/24&passphrase=userpass1"
配置文件
services:
- name: tun
addr: :0
handler:
type: tun
metadata:
keepAlive: true
ttl: 10s
passphrase: userpass1
listener:
type: tun
metadata:
net: 192.168.123.2/24
route: 192.168.101.0/24
forwarder:
nodes:
- name: target-0
addr: 1.2.3.4:8421
安全传输¶
GOST中的TUN数据目前是明文传输的,如果需要加密,客户端可以使用转发链配合加密隧道来提高安全性。可以使用基于TCP的隧道,例如tls,wss,grpc等,也可以使用基于UDP的隧道,例如kcp, quic等。
命令行
gost -L "tun://:0/:8421?net=192.168.123.2/24&keepAlive=true&route=192.168.101.0/24" -F relay+wss://1.2.3.4:443
配置文件
services:
- name: tun
addr: :0
handler:
type: tun
chain: chain-0
metadata:
keepAlive: true
ttl: 10s
listener:
type: tun
metadata:
net: 192.168.123.2/24
route: 192.168.101.0/24
forwarder:
nodes:
- name: target-0
addr: :8421
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 1.2.3.4:443
connector:
type: relay
dialer:
type: wss
使用转发链还有一个额外的好处,服务端可以不用暴露TUN服务的端口(8421),仅需要暴露隧道的端口(443),让VPN更加隐蔽。
-----------------------------------------------------------
流量控制-分流器
ginuerzh · 2022-08-27 12:00 · 30min read
所谓的分流是指按照一定的规则对流量进行划分,再对划分后的流量执行相应的操作,以达到某种程度的流量控制。
举一个现实中的例子,对于一个网络管控比较严格的公司,流量大概可以分为以下几类:
非法流量 - 不被允许的流量,例如被公司禁止访问的服务,直接访问会被拒绝。
内网流量 - 例如访问公司内部服务器,这种流量只能在公司内网才有效,不能被转发到外网。
外网流量 - 例如访问外网服务,可能需要通过公司的代理服务器才能访问。
GOST中的分流¶
GOST最早是在v2.6版本中增加了分流的功能,可以通过设置一组分流规则来对流量进行划分,主要用在转发链上,根据请求的目标地址来确定路由规则。
分流的功能也被带到了v3版本中,叫做分流器。起初和v2版本中的功能基本上没有什么区别,但在v3.0.0-beta.4版本中对分流器的功能进行了增强,支持了分流器组,可以在一个对象上设置多个分流器以达到一种组合效果,同时节点上的分流器功能也做了改动。
分流器类型¶
按照分流器设置的位置,分流器的功能也有所不同。
服务上的分流器¶
当服务上设置了分流器,如果请求的目标地址未通过分流器(未匹配白名单规则或匹配黑名单规则),则此请求会被拒绝。
命令行
gost -L http://:8080?bypass=example.com
配置文件
services:
- name: service-0
addr: ":8080"
bypass: bypass-0
handler:
type: http
listener:
type: tcp
bypasses:
- name: bypass-0
matchers:
- example.com
8080端口的HTTP代理服务使用了黑名单分流,example.org的请求会正常处理,example.com的请求会被拒绝。
这种分流器可以用来处理非法流量,将非法请求过滤掉。
分流器组¶
通过分流器组可以实现更加细粒度的控制,当任何一个分流器测试失败则代表未通过。
配置文件
services:
- name: service-0
addr: ":8080"
bypasses:
- bypass-0
- bypass-1
handler:
type: http
chain: chain-0
listener:
type: tcp
bypasses:
- name: bypass-0
whitelist: true
matchers:
- 192.168.0.0/16
- *.example.org
- name: bypass-1
matchers:
- 192.168.0.1
- www.example.org
以上分流器规则限定只有192.168.0.0/16网段(除了192.168.0.1)和匹配*.example.org(除了www.example.org)的域名的请求才能通过。
转发链层级分流器¶
当转发链层级或跳跃点(Hop)上设置了分流器,如果请求的目标地址未通过分流器(未匹配白名单规则或匹配黑名单规则),则转发链将终止于此跳跃点,且不包括此跳跃点。
这种类型的分流器可以看作是纵向(垂直)分流,在转发链的纵深方向上对请求进行层层过滤。
命令行
gost -L http://:8080 -F http://:8081?bypass=~example.com,.example.org -F http://:8082?bypass=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
bypass: bypass-0
nodes:
- name: node-0
addr: :8081
connector:
type: http
dialer:
type: tcp
- name: hop-1
bypass: bypass-1
nodes:
- name: node-0
addr: :8082
connector:
type: http
dialer:
type: tcp
bypasses:
- name: bypass-0
whitelist: true
matchers:
- example.com
- .example.org
- name: bypass-1
matchers:
- example.com
当请求www.example.com时未通过第一个跳跃点(hop-0)的分流器(bypass-0),因此请求不会使用转发链。
当请求example.com时,通过第一个跳跃点(hop-0)的分流器(bypass-0),但未通过第二个跳跃点(hop-1)的分流器(bypass-1),因此请求将使用转发链第一层级的节点(:8081)进行数据转发。
当请求www.example.org时,通过两个跳跃点的分流器,因此请求将使用完整的转发链进行转发。
节点上的分流器¶
当转发链使用多个节点时,可以通过在节点上设置分流器来对请求进行更加细粒度分流。
这种类型的分流器可以看作是横向(水平)分流,在单个层级或跳跃点上对请求进行划分。
分流器优先于节点选择器(Selector),因此会对节点选择的最终结果产生影响。
配置文件
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: :8081
bypass: bypass-0
connector:
type: http
dialer:
type: tcp
- name: node-1
addr: :8082
bypass: bypass-1
connector:
type: http
dialer:
type: tcp
bypasses:
- name: bypass-0
matchers:
- example.org
- name: bypass-1
matchers:
- example.com
当请求example.com时,通过了节点node-0上的分流器bypass-0,但未通过节点node-1上的分流器bypass-1,因此请求只会使用节点node-0进行转发。
当请求example.org时,未通过节点node-0上的分流器bypass-0,通过了节点node-1上的分流器,因此请求只会使用节点node-1进行转发。
DNS分流¶
在v3.0.0-beta.4版本中还有一个比较大的改进,DNS代理服务也增加了对分流器的支持。
DNS代理服务¶
与其他类型服务上的分流器类似,当DNS代理服务设置了分流器,如果DNS查询的域名未通过分流器(未匹配白名单规则或匹配黑名单规则),则DNS代理服务返回空结果。
命令行
gost -L dns://:10053/1.1.1.1?bypass=example.com
配置文件
services:
- name: service-0
addr: :10053
bypass: bypass-0
handler:
type: dns
listener:
type: dns
forwarder:
nodes:
- name: target-0
addr: 1.1.1.1
bypasses:
- name: bypass-0
matchers:
- example.com
当查询example.com时,未通过服务上的分流器bypass-0,查询将返回空结果。
DNS查询example.com(ipv4)
dig -p 10053 example.com
;; QUESTION SECTION:
;example.com. IN A
当查询example.org时,通过服务上的分流器bypass-0,查询将正常返回结果。
DNS查询example.org(ipv4)
dig -p 10053 example.org
;; QUESTION SECTION:
;example.org. IN A
;; ANSWER SECTION:
example.org. 74244 IN A 93.184.216.34
上游DNS服务节点上的分流器¶
类似于转发链节点上的分流器,DNS代理服务的转发器节点上也可以通过设置分流器来实现精细化分流。
配置文件
services:
- name: service-0
addr: :10053
handler:
type: dns
listener:
type: dns
forwarder:
nodes:
- name: target-0
addr: 1.1.1.1
bypass: bypass-0
- name: target-1
addr: 8.8.8.8
bypass: bypass-1
bypasses:
- name: bypass-0
matchers:
- example.org
- name: bypass-1
matchers:
- example.com
当查询example.org时,未通过目标节点target-0上的分流器bypass-0,通过了目标节点target-1的分流器bypass-1,查询将转发给节点target-1进行处理。
当查询example.com时,通过目标节点target-0上的分流器bypass-0,未通过目标节点target-1的分流器bypass-1,查询将转发给节点target-0进行处理。
组合使用¶
这里还是以公司网络为例将以上几种类型的分流器组合在一起使用。
假如在公司内部我们要访问进行以下几个域名的查询请求:
illegal-domain.corp - 非法的域名,无法解析。
domain.corp - 公司内网服务器域名,只有使用公司内部DNS服务192.168.1.1:53才能解析。
sub-domain.corp - 子公司内网服务器域名,只有通过子公司内网DNS服务192.168.2.1:53才能解析,并且此DNS服务器需要通过公司的代理服务器192.168.1.1:1080才能访问。
配置文件
services:
- name: service-0
addr: :10053
bypass: bypass-service
handler:
type: dns
listener:
type: dns
forwarder:
nodes:
- name: target-0
addr: 192.168.1.1:53
bypass: bypass-target-0
- name: target-1
addr: 192.168.2.1:53
bypass: bypass-target-1
chains:
- name: chain-0
hops:
- name: hop-0
bypass: bypass-hop-0
nodes:
- name: node-0
addr: 192.168.1.1:1080
connector:
type: socks5
dialer:
type: tcp
bypasses:
- name: bypass-service
matchers:
- illegal-domain.corp
- name: bypass-hop-0
whitelist: true
matchers:
- 192.168.2.1
- name: bypass-target-0
matchers:
- sub-domain.corp
- name: bypass-target-1
whitelist: true
matchers:
- sub-domain.corp
当查询illegal-domain.corp时,未通过服务上的分流器bypass-service,因此查询返回空结果。
当查询domain.corp时,通过了服务上的分流器bypass-service,并且通过上游DNS服务节点target-0上的分流器bypass-target-0,未通过节点target-1上的分流器bypass-target-1,因此选择使用target-0(192.168.1.1:53)作为上游DNS服务。由于target-0未通过转发链hop-0上的分流器bypass-hop-0,因此不会使用转发链。 最终结果就是对domain.corp的查询使用公司内网DNS服务器192.168.1.1:53进行查询。
当查询sub-domain.corp时,通过了服务上的分流器bypass-service,并且通过上游DNS服务节点target-1上的分流器bypass-target-1,未通过节点target-0上的分流器bypass-target-0,因此选择使用target-1(192.168.2.1:53)作为上游DNS服务。由于target-1通过了转发链hop-0上的分流器bypass-hop-0,因此会使用转发链。 最终结果就是对sub-domain.corp的查询通过使用公司代理服务192.168.1.1:1080使用子公司内网DNS服务器192.168.2.1:53进行查询。
-----------------------------------------------------------
GOST v3动态分流功能的一种实现方式
ginuerzh · 2022-05-03 12:17 · 15min read
原文地址:https://groups.google.com/g/go-gost/c/b9Z0BcqUArw。
分流是指根据一定的规则让需要通过转发链的请求走转发链,不需要走转发链则绕过转发链。分流在GOST v3中通过分流器来实现(bypass),具体的使用方式可以参考https://gost.run/concepts/bypass/。
GOST v3中新增了一个记录器模块(https://gost.run/concepts/recorder/),可以看作是另外一种日志记录方式,有别于日志的是记录器可以针对特定的数据进行记录,例如记录服务的所有访问用户IP,所有访问的目标地址等。
分流器和记录器在GOST v3版本中都增加了对redis服务的支持,对于分流器可以从redis中动态加载规则,对于记录器则可以将数据记录到redis服务中。
利用以上的特性,就可以实现类似与COW(https://github.com/cyfdecyf/cow)所提供的自动分流功能,默认情况下请求不使用转发链,当请求失败后切换为使用转发链。
目前的记录器可以记录所有访问失败的目标地址,将这些地址记录到redis中,再将分流器的数据源设置为redis中与记录器所记录的key相同,这样就可以通过记录器间接的找出并动态更新需要使用转发链的请求目标地址,提供给分流器使用。
services:
- name: service-0
addr: ":8080"
recorders:
- name: recorder-0
record: recorder.service.router.dial.address.error
handler:
type: http
chain: chain-0
listener:
type: tcp
chains:
- name: chain-0
hops:
- name: hop-0
bypass: bypass-0
nodes:
- name: node-0
addr: 192.168.1.1:8080
connector:
type: http
dialer:
type: tcp
bypasses:
- name: bypass-0
redis:
addr: 127.0.0.1:6379
db: 0
password: 123456
key: gost:bypasses:bypass-0
recorders:
- name: recorder-0
redis:
addr: 127.0.0.1:6379
db: 0
password: 123456
key: gost:bypasses:bypass-0
type: set
这种方法也存在一定的问题:
无法自动消除误判。当网络出问题时,会导致原本不需要使用转发链的请求目标地址也会被记录器记录。
此方式只对直连的请求建立连接时会报错的情况有效(例如请求超时,连接拒绝等),对于连接建立成功但无响应数据的情况无效。
针对第一种情况,可以借助外部工具,定期检查记录列表中每一个地址的直连状态,如果直连成功则可以将其清除。
如果你有更好的解决方案,欢迎提出!
-----------------------------------------------------------
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
发表评论: