menu Chancel's blog
rss_feed
Chancel's blog
我就是这样的人

Gost虚拟组网实践

作者:Chancel, 更新:2023 May 25, 字数:5070, 已阅:18

1. 基础知识

在公司想用家里的网络?FrpNgrok是个不错的选择

但这两者更新配置很麻烦,且只能做到点到点的穿透

虚拟组网相较于这两者的优势

  • 点到点的网络(P2P)
  • 随时访问局域网内所有设备
  • 更安全的传输协议

实现VPN虚拟组网的工具非常多,如ZeroiterTailscaleWireGuard等,都是非常棒的工具

我的需求比较简单,只需实现公司/家的联网,因有公网服务器,所以对NAT穿透无要求

如上,Gost便可满足我的需求了

如果需要NAT穿透建议看看ZeroiterTailscale

下面是一次基于Gost虚拟组网的实践记录

2. 实践

2.1. 背景

网络A的信息

  • 网段:192.168.100.0/24
  • GOST客户端(PC-A):192.168.100.100
  • 路由器:192.168.100.1

网络B的信息

  • 网段:192.168.200.0/24
  • GOST客户端(PC-B):192.168.200.200

公网服务器

  • IP:1.2.3.4

需求是实现网段B任意访问网段A内的所有设备,如PC-A或路由器,以下实践均基于以上信息

2.2. 服务器设置

下载Gost

  • https://github.com/go-gost/gost/releases/tag/v3.0.0-rc8

解压后目录如下

chancel@Tencent-Lighthouse ~/apps/gost$ tree                          
.
├── gost_3.0.0-rc8_linux_amd64v3.tar.gz
├── gost
├── LICENSE
├── README_en.md
└── README.md

在目录下创建config.yml配置文件,让Gost服务监听28443端口,并采用tls+relay加密转发udp数据到18421端口

配置文件内容如下

services:

- name: tls-tun
  addr: :28443 # 监听端口(客户端连接端口)
  handler:
    type: relay # 转发协议
  listener:
    type: tls # 加密数据通道
  forwarder:
    nodes:
    - name: target-0
      addr: :18421 # 转发的端口对象

- name: tun
  addr: 127.0.0.1:18421 # 绑定本地端口(不暴露此端口)
  handler:
    type: tun
    auther: tun
  listener:
    type: tun
    metadata:
      net: 172.16.16.1/24
      routes:
      - "192.168.100.0/24 172.16.16.100" # PC-A所在网络
      - "192.168.200.0/20 172.16.16.200" # PC-B所在网络

因创建tun设备需要root权限,使用sudo运行此配置,并检查对应日志输出,没有看到error信息即可

sudo gost -C config.yml

检查网卡信息,检查tun0设备信息,如下

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    ...
8: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1350 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 172.16.16.1/24 brd 172.16.16.255 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::dc8:d8db:4086:9b3b/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

2.3. 客户端设置

PC-A(192.168.100.100)客户端下载Gost

  • https://github.com/go-gost/gost/releases/tag/v3.0.0-rc8

解压后目录如下

chancel@Tencent-Lighthouse ~/apps/gost$ tree
.
├── gost_3.0.0-rc8_linux_amd64v3.tar.gz
├── gost
├── LICENSE
├── README_en.md
└── README.md

同样在目录下创建config.yml配置文件,内容如下

services:
- name: tun
  addr: :0
  handler:
    type: tun
    chain: chain-tls-tun # 对应chains中的 chain-tls-tun 节点
    metadata:
      keepAlive: true
      ttl: 10s
  listener:
    type: tun
    metadata:
      net: 172.16.16.100/24 # 对应服务器配置中的 metadata 配置
      route: 192.168.200.0/24 # 需要访问的网络,所以这里填PC-B的网段,如果有多个网段,则写成数组形式
  forwarder:
    nodes:
    - name: target-0
      addr: ":48421"

chains:
- name: chain-tls-tun
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: 1.2.3.4:28443 # 对应服务器配置的tls+relay监听端口
      connector:
        type: relay
      dialer:
        type: tls

创建tun设备需要root权限,运行此配置,并检查输出,没有看到error信息即可

sudo gost -C config.yml

同样的,PC-B(192.168.100.200)下载Gost并在目录下创建config.yml配置文件,内容如下

services:
- name: tun
  addr: :0
  handler:
    type: tun
    chain: chain-tls-tun # 对应chains中的 chain-tls-tun 节点
    metadata:
      keepAlive: true
      ttl: 10s
  listener:
    type: tun
    metadata:
      net: 172.16.16.200/24  # 对应服务器配置中的 metadata 配置
      route: 192.168.100.0/24 # 需要访问的网络,所以这里填PC-A的网段,如果有多个网段,则写成数组形式
  forwarder:
    nodes:
    - name: target-0
      addr: ":48421"

chains:
- name: chain-tls-tun
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: 1.2.3.4:28443 # 对应服务器配置的tls+relay监听端口
      connector:
        type: relay
      dialer:
        type: tls

因创建tun设备需要root权限,使用sudo运行此配置,并检查输出,没有看到error信息即可

sudo gost -C config.yml

以上设置完毕后,在PC-B机器上Ping一下机器PC-A以验证组网成功

chancel@nuc8i5 ~$ ping 192.168.100.100  
PING 192.168.100.100(192.168.100.100) 56(84) bytes of data.
64 bytes from 192.168.100.100: icmp_seq=1 ttl=63 time=13.8 ms
64 bytes from 192.168.100.100: icmp_seq=2 ttl=63 time=12.3 ms
64 bytes from 192.168.100.100: icmp_seq=3 ttl=63 time=12.5 ms
...

PC-B上查看一下当前路由规则,可以看到192.168.100.0的数据包默认发送到设备tun0

default via 192.168.31.1 dev wlp3s0 proto dhcp src 192.168.31.50 metric 600 
172.16.16.0/24 dev tun0 proto kernel scope link src 172.16.16.3 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.100.0/24 dev tun0

2.4. 防火墙设置

到上一步组网就完成了,但我们在PC-B上尝试一下Ping网络A的路由器,发现无法连接

chancel@nuc8i5 ~$ ping 192.168.100.1
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
--- 192.168.100.1 ping statistics ---
13 packets transmitted, 0 received, 100% packet loss, time 12282ms

这是因为数据包虽然被PC-A接收了,但私有网络的数据包无法正常转发到其他设备上,需要添加如下NAT规则才可以正常转发数据包

sudo iptables -t nat -A POSTROUTING -s 172.16.16.0/24 ! -o tun0 -j MASQUERADE

3. 结束

到这里虚拟组网的设置就结束了,相较于原作者的博文补充了一些实践上的信息,关于更多信息如认证、采用tcp连接可以参考作者的博文

参考资料

  • https://gost.run/blog/2022/tun/
  • https://juejin.cn/post/7214378356685684797

[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]
目录