关于 DreamCat

主题名称:DreamCat | 版本:3.0.240224

主题开发:HanFengA7 | CornWorld

Designed by HanFengA7 Power by Typecho

Copyright © 2015-2025 by LychApe All rights reserved!

menu
refresh

使用容器给vyos添加Tinc-VPN/Zerotier并配置OSPF

作者: ciaoℒy

时间:

得益于vyos内置的容器(Podman)支持, 给vyos扩展功能还是挺简单的. 再加上它是一个基于Debian的标准Linux发行版, 很多功能都可以用apt补充, 综合起来这个路由器系统还是挺好用的 (毕竟免费嘛).

自建docker仓库

本来我是想用podman load命令加载一个离线构建的tinc镜像的, 然而使用podman load导入的镜像并不能被vyos的配置系统识别到. 就是说, 使用podman load tinc.tar.gz, 然后用标准的配置指令set container name tinc image my-namespace/tinc:latest, 它会提示找不到镜像. 而如果是按照它的报错提示运行add container image my-namespace/tinc:latest的话, 则会直接去docker.io拉取镜像 (但是怎么能拉取得到呢?)

所以就需要自建一个docker仓库了. 自建仓库很简单, 用sonatype/nexus3就可以了. 不过这里有一个"坑"点, 新版的nexus3建议你给仓库的路由方式选用Path-Based Routing方式, 然而我试了N多错误路径之后发现, vyos上的podman在请求manifest信息时死活不会按照它支持的路径请求, 所以这边建议为了节约生命, 统一使用Port Connectors.

推荐的最佳实践是做一个hosted, N个proxy (例如一个docker.io和一个ghcr.io), 最后用一个group给统一起来. 这个方案挺不错的, 新版的nexus3还支持在webui中设置HTTP代理, 这样就可以很方便的给docker-cli挂代理了.

给vyos设置镜像的配置命令:

set container registry 192.168.1.2:8082 authentication password 'password'
set container registry 192.168.1.2:8082 authentication username 'username'
set container registry 192.168.1.2:8082 insecure
set container registry 192.168.1.2:8082 mirror address '192.168.1.2'
set container registry 192.168.1.2:8082 mirror port '8082'

这里需要注意一个事情, vyos的podman在拉取镜像时默认会向registry name发起请求. 这个操作就很不理解, 比如你如果命名的registry nameexample.com, 那么它就会向example.com发起请求拉取镜像, 而不是向mirror address. 说实话这一点我没理解为何要这样设计. 但是为了适应这个规则, 在registry name里就要把仓库的IP和端口都写上了.

容器配置

这块没啥好说的, 直接上配置代码:

set container name vpn-tinc allow-host-networks
set container name vpn-tinc arguments '-D -n tinc_net'
set container name vpn-tinc capability 'net-admin'
set container name vpn-tinc device tun destination '/dev/net/tun'
set container name vpn-tinc device tun source '/dev/net/tun'
set container name vpn-tinc image '192.168.1.2:8082/my-namespace/tinc'
set container name vpn-tinc volume tinc-etc destination '/etc/tinc'
set container name vpn-tinc volume tinc-etc source '/config/user-data/container/vpn/tinc/data/etc/tinc'
set container name vpn-tinc volume tinc-localtime destination '/etc/localtime'
set container name vpn-tinc volume tinc-localtime source '/etc/localtime'
set container name vpn-zerotier allow-host-networks
set container name vpn-zerotier capability 'net-admin'
set container name vpn-zerotier command '<这里是zerotier的网络id>'
set container name vpn-zerotier device tun destination '/dev/net/tun'
set container name vpn-zerotier device tun source '/dev/net/tun'
set container name vpn-zerotier image 'zerotier/zerotier:latest'
set container name vpn-zerotier volume zerotier-lib destination '/var/lib/zerotier-one'
set container name vpn-zerotier volume zerotier-lib source '/config/user-data/container/vpn/zerotier/data/var/lib/zerotier-one'

tinc配置

在tinc的配置方面, 一切按照标准的Linux上的操作即可. 不过这里有几个地方需要注意

  1. 我给的上述配置里并没有生成公私钥对的操作, 所以需要自己生成公私钥对. 可以通过podman exec命令生成
  2. [重要]tinc.conf中必须指定Interface = ethN, 这里的N是一个数字, 并且不能和主机原有的eth口冲突
  3. 可以不在tinc-up.sh中给接口配置IP, 因为在vyos的配置界面我们还要给接口添加ip

zerotier配置

zerotier的配置也比较简单, 和标准的Linux上操作不同的也是要给接口改个名字叫ethN. 这一点也是参考了社区的一篇文章: Level Zero Networking: Dynamic Multipoint VPN with ZeroTier and VyOS

# 容器中的文件路径是: /var/lib/zerotier-one/devicemap
cat >devicemap
# Example: <networkID>=<interface>
xxxxxxxxxxxxxxxx=eth10

接口配置

按照上面操作拉起两个容器之后, 使用show interface就能看到两个VPN生成的eth接口了. 之后进入配置界面配置一下接口就可以了:

set interfaces ethernet eth10 description 'Zerotier VPN'
# 为了能和其它主机上的zerotier接口通信, 这里需要设置成2800
set interfaces ethernet eth10 mtu '2800'

# tinc接口的IP也可以在tinc-up.sh中设置
set interfaces ethernet eth11 address '172.16.1.2/25'
set interfaces ethernet eth11 description 'Tinc VPN'

这里要注意一个, 使用vyos接管了zerotier的接口之后, 它把接口的MTU设置成5000了, 然而对端的MTU都是2800, 这里我指定了一下MTU的值就能通信了.

防火墙配置

防火墙的配置就不多说了, 我是为VPN接口新建了一个VPN域, 基本策略是: 放行LANVPN的双向流量/拒绝VPNWAN的双向流量/限制VPNLOCAL的流量.

# 此处省略部分配置, 只显示VPN相关配置
set firewall ipv4 name LAN-VPN default-action 'accept'
set firewall ipv4 name LOCAL-VPN default-action 'accept'
set firewall ipv4 name VPN-LAN default-action 'accept'
set firewall ipv4 name VPN-LOCAL default-action 'drop'
set firewall ipv4 name VPN-LOCAL rule 10 action 'accept'
set firewall ipv4 name VPN-LOCAL rule 10 protocol 'ospf'
set firewall ipv4 name VPN-LOCAL rule 20 action 'accept'
set firewall ipv4 name VPN-LOCAL rule 20 state 'established'
set firewall ipv4 name VPN-LOCAL rule 20 state 'related'
set firewall ipv4 name VPN-LOCAL rule 30 action 'accept'
set firewall ipv4 name VPN-LOCAL rule 30 protocol 'icmp'
set firewall ipv4 name VPN-LOCAL rule 40 action 'accept'
set firewall ipv4 name VPN-LOCAL rule 40 destination port '22'
set firewall ipv4 name VPN-LOCAL rule 40 protocol 'tcp_udp'
set firewall ipv4 name VPN-LOCAL rule 50 action 'drop'
set firewall ipv4 name VPN-LOCAL rule 50 description '不允许mesh-vpn之间互相走'
set firewall ipv4 name VPN-LOCAL rule 50 destination port '9993,655'
set firewall ipv4 name VPN-LOCAL rule 50 disable
set firewall ipv4 name VPN-LOCAL rule 50 protocol 'tcp_udp'
set firewall ipv4 name VPN-WAN default-action 'drop'
set firewall ipv4 name WAN-VPN default-action 'drop'
set firewall ipv4 name WAN-VPN rule 20 action 'accept'
set firewall ipv4 name WAN-VPN rule 20 state 'established'
set firewall ipv4 name WAN-VPN rule 20 state 'related'
# ipv6是一样的就不写了

set firewall zone LAN from VPN firewall name 'VPN-LAN'
set firewall zone LAN member interface 'br0'
set firewall zone LOCAL from VPN firewall name 'VPN-LOCAL'
set firewall zone LOCAL local-zone
set firewall zone VPN description 'mesh vpn'
set firewall zone VPN from LAN firewall name 'LAN-VPN'
set firewall zone VPN from LOCAL firewall name 'LOCAL-VPN'
set firewall zone VPN from WAN firewall name 'WAN-VPN'
set firewall zone VPN member interface 'eth11'
set firewall zone VPN member interface 'eth10'

这里我默认禁止了从VPN域进入主机的流量, 尤其是单独禁止了到主机9993和655端口的流量. 主要是防止zerotier和tinc的流量走VPN接口过来, 避免这俩mesh vpn误认为两台设备处于同一个局域网中出现套娃的情况. 当然我也不知道这样子操作对不对就是了

补充Linux上的操作

因为我的对端提供OSPF的设备是一台Ubuntu Server服务器, 所以也需要配置防火墙. 我用的ufw配置防火墙, 需要放行OSPF流量. 然而ufw防火墙的cli接口功能有限, 放行OSPF流量需要在配置文件里加规则:

# 在/etc/ufw/before.rules的filter配置表中添加规则
# Allow OSPFv2 only on specific interfaces
-A ufw-before-input -i enp1s0 -p 89 -j ACCEPT
-A ufw-before-input -i <这里是zerotier的接口> -p 89 -j ACCEPT
-A ufw-before-input -i tinc -p 89 -j ACCEPT

# 同理, 在/etc/ufw/before6.rules的filter配置表中添加规则
# Allow OSPFv3 only on specific interfaces
-A ufw6-before-input -i enp1s0 -p 89 -j ACCEPT
-A ufw6-before-input -i <这里是zerotier的接口> -p 89 -j ACCEPT
-A ufw6-before-input -i candy   -p 89 -j ACCEPT

OSPF配置

vyos的ospf配置很简单

set protocols ospf area 0 network '192.168.1.0/24'
set protocols ospf area 0 network '172.16.1.1/25'
set protocols ospf area 0 network '172.17.1.1/24'
set protocols ospf interface br0
set protocols ospf interface eth10 cost '10'
set protocols ospf interface eth11 cost '20'
set protocols ospf parameters router-id '192.168.1.1'

补充Linux上的操作

Linux上用bird提供OSPF, 我用的是1.6版本的, 把ip a的运行结果发给gpt, 让gpt给写一个配置就可以了:

protocol kernel {
        scan time 60;
        import all;
        export all;   # Actually insert routes into the kernel routing table
}

protocol device {
        scan time 60;
}

router id 192.168.0.2;

protocol direct {
        interface "enp1s0";
        interface "<这里是zerotier的接口名称>";
        interface "tinc";
}

protocol ospf {
    import all;
    area 0.0.0.0 {
        interface "enp1s0" {
            type broadcast;
            cost 10;
        };
        interface "zerotier的接口名称" {
            type broadcast;
            cost 20;
        };
        interface "tinc" {
            type pointopoint;
            cost 30;
        };
    };
}

之后在vyos上使用show ip route ospfshow ip ospf neighbor检查路由表和邻居是否正常.

在Linux上则使用sudo birdc show ospf neighborssudo birdc show route查看.

另外, 在Linux上我遇到一个问题. 当我查看bird学习到的路由表时, 对端路由器网段192.168.1.0/24已经学到了; 然而使用命令ip route查看本机路由表却没有这条项目. 这就导致两边的LAN是不互通的. 问题的原因就是没有在bird.conf中把bird的路由表导出到系统路由表里, 所以就需要在protocol kernel里面加一个export all


#本文链接:https://blog.chaol.top/archives/103.html
#本文采用 CC BY-NC-SA 4.0 协议进行许可
#如无特别声明,该文章均为 ciaoℒy 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0)协议,即转载请注明文章来源。
#最后编辑时间为: 2025 年 09 月 27 日
none

create 添加新评论


account_circle
email
language
textsms



加我的QQ
加我的微博
加我的支付宝
加我的微信