软路由环境
操作系统:ArchLinux
硬件设备:J1900
、4
个I211
千兆网卡
思路
网络拓扑图如下:所有流量经软路由处理,墙内流量直接转发到上级路由处理,墙外流量走本地翻墙软件处理后转发到上级路由。
使用的软件:
smartdns
:可以配置多个上游DNS
服务器,支持使用TLS
和HTTPS
进行查询,配合GFWList
,所有需要翻墙的域名解析都通过TCP
形式发送到上有DNS
服务器做域名解析。dhcpd
:用于动态分配LAN
口设备接入的IP
配置信息。ss-redir
:配合iptables
将所有需要翻墙的数据发送到ss-redir
(通过修改数据目的地址为本机ss-redir
监听地址)。systemd-networkd
:管理网卡。iptables
:处理包。
DNS数据流
DNS
查询请求由软路由smartdns
处理。- 根据域名判断,墙外域名走
TLS
和HTTPS
形式进行查询,由于类型为TCP
,其数据流同下节路由器本机TCP
数据流。 - 其余域名走国内
DNS
服务器查询,直接通过WAN
口发送到光猫。
LAN口转发TCP数据流
- 硬路由数据由
LAN
口流入,判断IP
地址是否为私有或者墙内。 IP
范围如果是私有地址或者为墙内地址范围,将源IP
改为本机(SNAT
),即10.10.10.10->192.168.1.2
,否则回程时,上层光猫看不见10.10.10.10
子网(这里还有一种方案,不做SNAT
,直接在上层光猫加路由表)。- 其余
IP
,利用iptables
修改目的IP
为本机,转发到本机ss-redir
端口,ss-redir
会拿到其REDIRECT
前目的IP
地址,做一层封装后通过WAN
发送到远端SS
服务器,SS
服务器解析出目的IP
地址并访问,最后将返程数据发回ss-redir
进程,ss-redir
拿到返程数据后原路返回。
路由器本机TCP数据流
同上,只是第二步的SNAT
可以省去,因为源IP
已经是当前路由器发出的。
步骤
一、网卡配置
这里只使用两个网口,enp1s0
和enp2s0
(使用ip addr
)可以查看MAC
地址和其他设备名称,分配enp1s0
为WAN
口,enp2s0
为LAN
口,记下两个网卡的MAC
地址。在/etc/systemd/network/
创建文件lan0.network
和wan0.network
注意后缀是.network
前面名字随意。
# wan0.network
# MACAddress 就是 enp1s0 的 mac 地址
# enp1s0 网口接光猫的 LAN 口
# 使用 DHCP 从光猫处获取 IP 地址和网关地址
[Match]
MACAddress=00:e0:4c:68:78:c4
[Network]
DHCP=yes
# lan0.network
# MACAddress 就是 enp2s0 的 mac 地址
# 硬路由 WAN 口接软路由的 enp2s0 网口
# 分配该网口的 IP 为 10.10.10.1 子网为 10.10.10.xxx/24
[Match]
MACAddress=00:e0:4c:68:78:c5
[Network]
Address=10.10.10.1/24
# 启动 systemd-networkd 服务配置网口
# 注意不要启动和他有冲突的软件,例如 networkmanager
systemctl enable systemd-networkd.service
systemctl start systemd-networkd.service
二、DHCP服务器配置
配置文件(IPV4
): /etc/dhcpd.conf
,这里不使用IPV6
。
subnet 10.10.10.0 netmask 255.255.255.0 {
option subnet-mask 255.255.255.0;
# 将网关和dns服务器都设置为软路由
option domain-name-servers 10.10.10.1;
option routers 10.10.10.1;
# 分配地址范围
range 10.10.10.10 10.10.10.100;
}
# 启动 dhcpd 服务
systemctl enable dhcpd.service
systemctl start dhcpd.service
三、DNS服务器配置
smartdns
配置文件在/etc/smartdns/smartdns.conf
。
bind [::]:53
cache-size 16383
cache-persist yes
cache-file /tmp/smartdns.cache
force-qtype-SOA 65
log-level info
# DNS 服务器配置
server 119.29.29.29
server 223.5.5.5
# 配置 TLS 和 HTTPS 的 DNS 服务器地址
# 仅 GFW 域名列表中的域名会用以下服务器
server-tls 8.8.8.8:853 -group GFW -exclude-default-group
server-tls 8.8.4.4:853 -group GFW -exclude-default-group
server-https https://dns.google/dns-query -group GFW -exclude-default-group
# GFW LIST
conf-file /etc/smartdns/gfw.conf
生成gfw.conf
文件后放在/etc/smartdns/gfw.conf
。生成列表文件的脚本:
#!/bin/bash
curl -sS https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt | \
base64 -d | sort -u | sed '/^$\|@@/d'| sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' | \
sed '/apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /qq\.com/d' | \
sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' | grep '^[0-9a-zA-Z\.-]\+$' | \
grep '\.' | sed 's#^\.\+##' | sort -u > /tmp/temp_gfwlist1
curl -sS https://raw.githubusercontent.com/hq450/fancyss/master/rules/gfwlist.conf | \
sed 's/ipset=\/\.//g; s/\/gfwlist//g; /^server/d' > /tmp/temp_gfwlist2
curl -sS https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/gfw.txt > /tmp/temp_gfwlist3
cat /tmp/temp_gfwlist1 /tmp/temp_gfwlist2 /tmp/temp_gfwlist3 | \
sort -u | sed 's/^\.*//g' > /tmp/temp_gfwlist
cat /tmp/temp_gfwlist | sed 's/^/\./g' > /tmp/smartdns_gfw_domain.conf
sed -i 's/^/nameserver \//' /tmp/smartdns_gfw_domain.conf
sed -i 's/$/\/GFW/' /tmp/smartdns_gfw_domain.conf
cp /tmp/smartdns_gfw_domain.conf gfw.conf
启动smartdns
服务
systemctl enable smartdns.service
systemctl start smartdns.service
四、防火墙iptables配置
这里一定要搞清楚流量是怎么跳转的,由于iptables
重启会失效,可以安装iptables-save
开机自动设置规则,或者放在开机执行脚本中 ,iptables
所有重要的链和表流程可以参考下图。
systemctl enable iptables.service
systemctl start iptables.service
# 获取国内 ip 地址范围
wget -P . http://www.ipdeny.com/ipblocks/data/countries/cn.zone
# 生成 cnzone ipset
ipset -N cnzone hash:net
for ip in $(cat $CN_ZONE); do
ipset -A cnzone $ip
done
iptables -t nat -N SS
# 私有IP地址放行
# 发往SS服务器端口为SS_SERVER_PORT的放行
# 在 cnzone ip 地址范围放行
# 其余转发到 ss-redir
iptables -t nat -A SS -p tcp --dport $SS_SERVER_PORT -j RETURN
iptables -t nat -A SS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SS -d 240.0.0.0/4 -j RETURN
iptables -t nat -A SS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SS -m set --match-set cnzone dst -j RETURN
iptables -t nat -A SS -p tcp -j REDIRECT --to-ports $SS_LOCAL_PORT
iptables -t nat -A PREROUTING -p tcp -j SS
iptables -t nat -A OUTPUT -p tcp -j SS
# 内网 - SNAT
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o $WAN0 -j MASQUERADE
五、ss-redir启动
# 将机场 ss 服务器配置文件保存到 conf 中
ss-redir -c $SS_CONFIG_FILE >> /var/log/ss-redir.log 2>&1 &