软路由环境

操作系统:ArchLinux

硬件设备:J19004I211千兆网卡

思路

网络拓扑图如下:所有流量经软路由处理,墙内流量直接转发到上级路由处理,墙外流量走本地翻墙软件处理后转发到上级路由。

router_archlinux_0

使用的软件:

  1. smartdns:可以配置多个上游DNS服务器,支持使用TLSHTTPS进行查询,配合GFWList,所有需要翻墙的域名解析都通过TCP形式发送到上有DNS服务器做域名解析。
  2. dhcpd:用于动态分配LAN口设备接入的IP配置信息。
  3. ss-redir:配合iptables将所有需要翻墙的数据发送到ss-redir(通过修改数据目的地址为本机ss-redir监听地址)。
  4. systemd-networkd:管理网卡。
  5. iptables:处理包。

DNS数据流

  1. DNS查询请求由软路由smartdns处理。
  2. 根据域名判断,墙外域名走TLSHTTPS形式进行查询,由于类型为TCP,其数据流同下节路由器本机TCP数据流。
  3. 其余域名走国内DNS服务器查询,直接通过WAN口发送到光猫。

LAN口转发TCP数据流

  1. 硬路由数据由LAN口流入,判断IP地址是否为私有或者墙内。
  2. IP范围如果是私有地址或者为墙内地址范围,将源IP改为本机(SNAT),即10.10.10.10->192.168.1.2,否则回程时,上层光猫看不见10.10.10.10子网(这里还有一种方案,不做SNAT,直接在上层光猫加路由表)。
  3. 其余IP,利用iptables修改目的IP为本机,转发到本机ss-redir端口,ss-redir会拿到其REDIRECT前目的IP地址,做一层封装后通过WAN发送到远端SS服务器,SS服务器解析出目的IP地址并访问,最后将返程数据发回ss-redir进程,ss-redir拿到返程数据后原路返回。

路由器本机TCP数据流

同上,只是第二步的SNAT可以省去,因为源IP已经是当前路由器发出的。

步骤

一、网卡配置

这里只使用两个网口,enp1s0enp2s0(使用ip addr)可以查看MAC地址和其他设备名称,分配enp1s0WAN口,enp2s0LAN口,记下两个网卡的MAC地址。在/etc/systemd/network/创建文件lan0.networkwan0.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所有重要的链和表流程可以参考下图。

router_archlinux_1

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 &
最后修改:2023 年 01 月 23 日
如果觉得我的文章对你有用,请随意赞赏