wd and cc

— Happy every day

Setup Policy Route on Openwrt X86 With Wireguard

Posted at — Nov 6, 2021

刷系统

选择 image,我用的是 x86_64 的硬件。如果你不确定,可以选择 generic 的试试看,如果你能用 64 的,启动的时候提示你用 64 位的性能更好。

然后需要选择不同的包,主要是在下面两个里面选。

准备两个 u 盘。如果你能有一个 u 盘可以启动加存放那个 img 那就更好了。

连接显示器,键盘。

先使用 livecd 启动之后,先确认下盘符。一般 /dev/sda 是内置的磁盘,/dev/sdb 是 livecd。确认后插入另外一个 u 盘,这个的盘符应该是 /dev/sdc。

mount /dev/sdc1 /mnt
cd /mnt
dd if=openwrt-21.02.0-x86-64-generic-ext4-combined.img of=/dev/sda

使用 cfdisk resize 下 /dev/sda2 并写到分区表。然后使用 resize2fs /dev/sda2 命令应用到文件系统。这个时候就可以使用路由器自带的 openwrt 启动了。

初始化

system -> system

system -> administration

ssh [email protected] 测试连接。

调整网络配置

调整的主要原因是

调整内容

使用 dnsmasq-full 替换 dnsmasq

这一步需要通过 ssh 操作。这一步放最前面是为了避免丢失配置,因为为了省事(解决配置冲突)需要删除 /etc/config/dhcp

opkg update
opkg remove dnsmasq # 这一步可能会导致 dns 丢失,如果出现问题可以去 /etc/resolve.conf 里面重新配置下 dns
rm /etc/config/dhcp
opkg install dnsmasq-full

网络拓扑

openwrt -> wifi router -> pc/mac/iphone 10.10.10.1/24 -> 10.10.10.2/10.10.8.1/24 -> 10.10.8.x

这样的结构下,如果 openwrt 出问题,可以随时把外网接 wifi router 上面继续用,其他设备都不用动。等稳定之后,可以把 wifi router 改成桥接模式。

配置 wireguard

参考文档:https://openwrt.org/docs/guide-user/services/vpn/wireguard/server

规划下 wireguard 各个节点的 ip

这里需要提前规划下 wireguard 网络,我的目的是通过远端的 vps 上网,所以我的设置如下

安装配置 wireguard

这个时候可能需要重启下路由器才能继续,否则可能在菜单里面看不到 wireguard 这个选项

这个时候执行 wg 命令应该可以看到 wg 设备的情况了。在 status -> wireguard 也可以看到。如果想要在这里支持 qr/code ,还需要安装一些 qrcode 相关的包。

配置 firewall

单独为 wg 创建一个 zone。允许通过 wg 访问 wan 和 lan。

允许通过 wan 访问 54321

配置 wireguard peers

这个时候执行 wg 命令或者去 status -> wireguard 应该能看到更多信息了。比较关键的是确认下 vps 那个有没有连接成功,看 latest handshake 是什么时候。

peer: <pub_key>
  endpoint: <ip:port>
  allowed ips: 0.0.0.0/0
  latest handshake: 45 seconds ago
  transfer: 92 B received, 212 B sent
  persistent keepalive: every 25 seconds

也可以测试下是不是可以通过电脑或者手机连接这个 openwrt 上面的 wireguard。这个时候应该只能 handshake 成功,但是不能通过这个连接访问任何网站,因为还没有配置相关的路由。DNS 也不通。

配置路由

配置针对 10.10.20.0/24 网段的路由,配置之后就可以通过 wg 访问路由器的ip 10.10.10.1 了。

route add -net 10.10.20.0 netmask 255.255.255.0 dev wg0

如果你还想通过 wg 访问内网的设备(10.10.8.x),还需要配置一条路由

network -> dhcp and dns -> static leases

network -> static routes -> add

注意几点

增加 route table

编辑 /etc/iproute2/rt_tables,增加一行

200 gfw

配置 dnsmasq 和 ipset

配置 ipset

安装 ipset

创建 /etc/gfw.ip.ipset 文件。里面存放需要通过 wg 访问的 ip。

8.8.8.8
1.1.1.1

创建 /etc/gfw.net.ipset 文件。里面存放需要通过 wg 访问的 cidr

# telegram
67.198.55.0/24
91.108.4.0/22
91.108.8.0/22
91.108.12.0/22
91.108.16.0/22
91.108.56.0/22
109.239.140.0/24
149.154.160.0/20
149.154.164.0/22
149.154.168.0/22
149.154.172.0/22
205.172.60.0/22

修改 /etc/config/firewall 文件。增加下面的内容

config ipset
    option name 'gfw'
    option match 'ip'
    option storage 'hash'
    option enabled '1'
    option loadfile '/etc/gfw.ip.ipset'
	
config ipset
    option name 'gfwnet'
    option match 'net'
    option storage 'hash'
    option enabled '1'
    option loadfile '/etc/gfw.net.ipset'

重启 firewall /etc/init.d/firewall restart. 执行 ipset list 查看结果

Name: gfwip
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 200
References: 0
Number of entries: 0
Members:
1.1.1.1
8.8.8.8

Name: gfwnet
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 1216
References: 0
Number of entries: 12
Members:
149.154.172.0/22
109.239.140.0/24
91.108.8.0/22
67.198.55.0/24
149.154.168.0/22
149.154.160.0/20
91.108.12.0/22
91.108.16.0/22
149.154.164.0/22
91.108.56.0/22
91.108.4.0/22
205.172.60.0/22

日后这两个文件 /etc/gfw.net.ipset/etc/gfw.ip.ipset 就是管理静态的需要走 wg 的 ip 的文件。

配置 dnsmasq

network -> dhcp and dns

这个配置之后应该可以通过 wg 访问 openwrt 的 dns 了。

创建 /etc/dnsmasq.d/gfw.conf 文件,可以根据需要自己写,也可以使用别人写好的。格式如下

server=/twitter.com/8.8.8.8
ipset=/twitter.com/gfwip

也可以使用我整理好的 https://github.com/wd/gfwlist-ipset/blob/main/gfwlist-ipset.conf

修改 /etc/config/dhcp 文件,增加一行

config dnsmasq
	...
	option confdir '/etc/dnsmasq.d'

重启 dnsmasq, /etc/init.d/dnsmasq restart. 测试下

# dig twitter.com

; <<>> DiG 9.17.13 <<>> twitter.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13344
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;twitter.com.                   IN      A

;; ANSWER SECTION:
twitter.com.            1227    IN      A       104.244.42.193
twitter.com.            1227    IN      A       104.244.42.1

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Oct 24 22:38:47 CST 2021
;; MSG SIZE  rcvd: 72

# ipset list gfwip
Name: gfwip
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 392
References: 0
Number of entries: 4
Members:
8.8.8.8
104.244.42.193
1.1.1.1
104.244.42.1

能看到 twitter ip 已经加入到了 ipset 里面。(这个测试里面不一定能返回正确的 twitter 的 ip,只是测试 dnsmasq + ipset 是正常工作的)。

以后需要翻墙的域名就在这个 /etc/dnsmasq.d/gfw.conf 文件里面维护。也可以在这个目录放多个文件。

配置匹配 ipset 的包走 wg

network -> firewall -> custom rules

iptables -t mangle -N fwmark
iptables -t mangle -A PREROUTING -j fwmark
iptables -t mangle -A OUTPUT -j fwmark

iptables -t mangle -A fwmark -m set --match-set gfwip dst -j MARK --set-mark 1
iptables -t mangle -A fwmark -m set --match-set gfwnet dst -j MARK --set-mark 1

路由规则

# 有 0x1 标记的,都走 gfw 这个 table
ip rule add fwmark 0x1 table gfw

# gfw 这个 table 默认都从 10.10.20.1 出去
ip route add default via 10.10.20.1 dev wg0 table gfw

配置 hotplug

上面的路由规则目前都是通过手动配置的,重启设备就没有了。需要配置一个自动添加的脚本。

创建一个文件 /etc/hotplug.d/iface/50-wg

#!/bin/sh

if [ "ifup" = "$ACTION" ] && [ "$INTERFACE" = "wg0" ]; then
        ip route add 10.10.20.0/24 dev wg0
        ip rule|grep -q 'fwmark 0x1 lookup gfw' || ip rule add fwmark 0x1 table gfw
        ip route add default via 10.10.20.1 dev wg0 table gfw
fi

排查错误

在全部配置好之后,最好重启下 openwrt,确保重启后依然是可以上网的。如果有问题,可以参考下面的步骤。

确保 ipset ok,应该有两个set gfwipgfwnet。查询一个被屏蔽的 dns 之后能在 ipset 列表里面看到。

# ipset list

确保路由规则都在

# ip route show table gfw
default via 10.10.20.1 dev wg0

# ip rule|grep fwmark
32765:  from all fwmark 0x1 lookup gfw

# ip route |grep wg
10.10.20.0/24 dev wg0 scope link

iptables 规则 ok

# iptables -t mangle -nvL PREROUTING
Chain PREROUTING (policy ACCEPT 26721 packets, 5880K bytes)
 pkts bytes target     prot opt in     out     source               destination
  27M   31G fwmark     all  --  *      *       0.0.0.0/0            0.0.0.0/0
 
# iptables -t mangle -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 6295 packets, 2828K bytes)
 pkts bytes target     prot opt in     out     source               destination
 307K   86M fwmark     all  --  *      *       0.0.0.0/0            0.0.0.0/0

# iptables -t mangle -nvL fwmark
Chain fwmark (2 references)
 pkts bytes target     prot opt in     out     source               destination
 188K   29M MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set gfwip dst MARK set 0x1
 1417  157K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set gfwnet dst MARK set 0x1

启用 log system -> logging

通过看 FORWARD 和 POSTROUTING 的日志来判断可能是哪里有问题。

DEST=8.8.8.8
iptables -t filter -A FORWARD -d $DEST -j LOG --log-prefix 'FWD:'
iptables -t mangle -A POSTROUTING -d $DEST -j LOG --log-prefix 'POST:'

DEST=10.10.8.1
iptables -t filter -D FORWARD -d $DEST -j LOG --log-prefix 'FWD:'
iptables -t mangle -D POSTROUTING -d $DEST -j LOG --log-prefix 'POST:'

如果只有 FORWARD 没有 POSTROUTING,那就是包被 drop 了。同时也观察包是否有正确的 src dst 和 mark。

其他

iptv

network -> interfaces -> add

安装 luci-app-udpxy

services -> udpxy

访问 http://10.10.10.1:4022/status 能看到 Multicast address 是 192.168.1.x 这样的 ip。可以找一个地址测试下是不是可以用吧。

ddns

安装 ddns-scripts-cloudflare ca-certificates

services -> ddns -> add

点击那个 reload 可以重复执行。点击 edit 可以看 log,如果遇到 ssl 错误,可能需要安装 libwolfssl4.8.1.66253b90,openwrt 默认使用 wolfssl

其他

TODO

comments powered by Disqus