用 CentOS 7 纯手工打造属于自己的软路由服务器


一、前言

自从了解了软路由这玩意之后,它强大的性能以及高自由度就一直让我羡慕不已。

但是作为“懂” Linux 以及计算机网络的我来说,如果直接使用现成的软路由系统总感觉低估了自己的能力……而且我家里也已经有了一台 Linux 服务器,要是能做到物尽其用那就最好了。

于是我很早就计划着搭建一台属于自己的软路由服务器。可惜由于懒癌发作,一直没有动手。直到半个月前,家里的旧路由器终于坏了,这时候我才着手去研究它……

前前后后折腾了一整天,总算是完工了!感觉收获了不少东西。想想还是很有必要把整个配置过程整理完然后给大家分享一下!

本文纯属个人学习经验分享,写得可能会比较乱,仅供参考。如有错误,可以的话请及时提出,谢谢!


二、基本情况

2.1 现有设备

  • 单网口 Linux 服务器一台(系统为 CentOS 7.5.1804,已关闭 SELinux)
  • 八口 Cisco 可网管交换机一台
  • 无线 AP 两台
  • 光猫一台(20M 移动光纤)

2.2 需求

  • 整个网络分为两个网段,一个供主人使用,另一个供客人使用。
  • 主人网络和客人网络均通过服务器进行 NAT 上网,IP 地址由服务器自动分配。
  • 主人网络和客人网络之间不能互访。
  • 服务器提供 DHCP、DNS、HTTP、HTTPS 等各种服务,主人网络可以访问所有服务,客人网络不可访问除 DNS、DHCP 之外的所有服务。
  • 为了方便地访问“外网”,需要在主人网络中部署透明代理服务,并且要做到自动分流“内外网”流量。

2.3 方案设计 & 原理简析

 
image

由于我的服务器上只有一个网口,所以必须配合划分了 VLAN 的交换机,把它当作一台单臂路由才能实现上述功能。

下面我划分了三个 VLAN:

  • VLAN 1:连接光猫(WAN)
  • VLAN 2:主人网络
  • VLAN 3:客人网络

以下是交换机端口及 VLAN 的配置表:

端口号 Gi0/1 Fa0/1 Fa0/2 Fa0/3 Fa0/4 Fa0/5 Fa0/6 Fa0/7 Fa0/8
端口模式 Trunk Access Access Access Access Access Access Access Access
(Native) VLAN 1 1 2 2 2 3 3 1 1
用途 连接服务器 连接光猫 连接主人 AP 连接主房内有线网口 连接主房内有线网口 连接客房内有线网口 连接客人 AP 未使用(关闭端口) 未使用(关闭端口)

以下是服务器网络接口的配置表:

接口名 VLAN ID IP 地址 用途
enp1s0 连接交换机的物理接口
vlan1@enp1s0 1 (自动获取) WAN 口
vlan2@enp1s0 2 192.168.200.1/24 主人网络接口
vlan3@enp1s0 3 192.168.201.1/24 客人网络接口

至于“外网”的访问,由于我的云主机流量充足,所以我使用「绕过大陆 IP」模式。

「双 S」-local 监听的地址和端口为 0.0.0.0:1080「双 S」-redir 监听的地址和端口为 0.0.0.0:1081

以下是“内外网”自动分流原理图:

 

 
image

 

说明
• 下面只介绍服务器网络接口、防火墙、DHCP 以及 DNS 服务器的配置方法,其他配置将不作过多的介绍。
• 由于需要大幅修改服务器网络接口的参数,所以建议使用带外(通过控制台)方式配置服务器。
• 如果大家需要参考使用我的配置,请先根据实际情况以及注释提示修改命令或配置文件再使用。


三、准备工作

3.1 卸载 CentOS 7 自带的防火墙

yum -y remove firewalld

3.2 卸载 NetworkManager

yum -y remove NetworkManager

3.3 安装必要的软件

yum -y install iptables-services ipset-service dnsmasq  # 安装 iptables、ipset 服务,还有用作 DNS 和 DHCP 服务器的 dnsmasq


四、配置网络接口

4.1 删除现有的接口配置文件

rm /etc/sysconfig/network-scripts/ifcfg-*

4.2 配置连接交换机的物理接口

cat << EOF > /etc/sysconfig/network-scripts/ifcfg-enp1s0
DEVICE=enp1s0   # 接口名
TYPE=Ethernet   # 接口类型为以太网
ONBOOT=yes      # 开机自动启动接口
USERCTL=no      # 不允许用户自行配置
BOOTPROTO=none  # 不自动获取 IP 地址
EOF

4.3 配置 WAN 接口

cat << EOF > /etc/sysconfig/network-scripts/ifcfg-vlan1
DEVICE=vlan1
TYPE=vlan   # 接口类型为 VLAN
VLAN=yes    # 开启 VLAN 功能
VLAN_ID=1   # 设置 VLAN ID
PHYSDEV=enp1s0  # 绑定的物理设备
ONBOOT=yes
USERCTL=no
BOOTPROTO=dhcp  # 通过 DHCP 获取 IP 地址
DEFROUTE=yes    # 作为默认网关接口
PEERDNS=no      # 手动配置 DNS
DNS=127.0.0.1
EOF

4.4 配置主人网络接口

cat << EOF > /etc/sysconfig/network-scripts/ifcfg-vlan2
DEVICE=vlan2
TYPE=vlan
VLAN=yes
VLAN_ID=2
PHYSDEV=enp1s0
ONBOOT=yes
USERCTL=no
BOOTPROTO=none
IPADDR=192.168.200.1
NETMASK=255.255.255.0
EOF

4.5 配置客人网络接口

cat << EOF > /etc/sysconfig/network-scripts/ifcfg-vlan3
DEVICE=vlan3
TYPE=vlan
VLAN=yes
VLAN_ID=3
PHYSDEV=enp1s0
ONBOOT=yes
USERCTL=no
BOOTPROTO=none
IPADDR=192.168.201.1
NETMASK=255.255.255.0
EOF

4.6 重启网络服务

systemctl restart network

4.7 开启 IPv4 转发

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

sysctl -p


五、配置 DNS、DHCP 服务

5.1 安装 & 配置 dns2socks

5.1.1 安装 dns2socks 主程序

说明
• 这个主程序是我自己编译的,我把它的默认监听地址和端口修改为 127.0.0.1:1083;上游 DNS 服务器修改为 8.8.8.8;SOCKS 服务器地址和端口修改为 127.0.0.1:1080。如果想自己编译的话请自行下载源代码

curl -s -o /usr/bin/dns2socks https://cloud.zenandidi.com/s/d9WMg3A8HlKrG3G/download

5.1.2 设置权限

chmod +x /usr/bin/dns2socks

5.1.3 安装 dns2socks 服务文件

cat << EOF > /lib/systemd/system/dns2socks.service
[Unit]
Description=Forward DNS requests to a DNS server via a SOCKS tunnel
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/dns2socks

[Install]
WantedBy=multi-user.target
EOF

5.1.4 启动服务

systemctl start dns2socks.service

5.1.5 设置开机自启动

systemctl enable dns2socks.service

5.2 配置 dnsmasq

5.2.1 备份原 dnsmasq 服务配置文件

mv /etc/dnsmasq.conf /etc/dnsmasq.conf.bak

5.2.2 创建 dnsmasq 主配置文件

cat << EOF > /etc/dnsmasq.conf
# 通用配置
conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig # 指定外部配置文件
resolv-file=/etc/resolv.dnsmasq.conf # 指定上游 DNS 服务器列表文件

# 主人网络 DHCP 服务器设置
dhcp-range=vlan2,192.168.200.2,192.168.200.254,255.255.255.0,86400s # DHCP 地址池设置(接口名,起始 IP,结束 IP,子网掩码,租约时间)
dhcp-option=vlan2,3,192.168.200.1 # 默认网关设置
dhcp-option=vlan2,6,192.168.200.1 # DHCP DNS 设置

# 客人网络 DHCP 服务器设置
dhcp-range=vlan3,192.168.201.2,192.168.201.254,255.255.255.0,86400s
dhcp-option=vlan3,3,192.168.201.1
dhcp-option=vlan3,6,192.168.201.1

# 静态 IP 设置格式
# dhcp-host=<以冒号分割的 MAC 地址>,<IP 地址>

EOF

下面把「可能被污染的域名」交由 dns2socks 解析。

curl -s https://cloud.zenandidi.com/s/9tw3jpWAx0Mo9Aa/download >> /etc/dnsmasq.conf

说明
• 由于「可能被污染的域名」列表较大,所以我把它打包成了一个文本文件然后放在我的服务器上。大家可以使用上面的命令将「可能被污染的域名」列表下载并直接导入到 dnsmasq 主配置文件中即可。
• 「可能被污染的域名」列表来源:KoolShare「双 S」插件(更新于 2018 年 04 月 22 日)。

5.2.3 创建上游 DNS 服务器列表文件

cat << EOF > /etc/resolv.dnsmasq.conf
# 格式(一行一个 DNS 服务器)
# nameserver <DNS 服务器地址>
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
nameserver 1.0.0.1
EOF

5.2.4 启动服务

systemctl start dnsmasq.service

5.2.5 设置开机自启动

systemctl enable dnsmasq.service


六、配置 ipset

6.1 启动服务

systemctl start ipset

6.2 设置开机自启动

systemctl enable ipset

6.3 清空地址集

ipset destroy

6.4 创建地址集

ipset create china_ip hash:net maxelem 65536 # 创建「大陆 IP 地址集」

6.5 往「大陆 IP 地址集」里面添加条目

说明
• 由于需要添加到「大陆 IP 地址集」中的条目较多,所以我把所有的命令打包成了一个脚本文件然后放在我的服务器上。大家可以直接使用我的脚本完成「大陆 IP 地址集」条目的添加。
• 「大陆 IP 地址集」条目来源:KoolShare「双 S」插件(更新于 2018 年 04 月 27 日)。

⚠️ 注意
• 直接运行从 curl 下载的脚本是非常危险的!大家尽量不要这样做,这里仅仅是为了方便而已!

curl -s https://cloud.zenandidi.com/s/oxc59TsC0JAP3db/download | bash -x

6.6 保存地址集

ipset save > /etc/sysconfig/ipset


七、配置 NAT & 防火墙

7.1 准备工作

systemctl stop iptables     # 停止服务
systemctl start iptables    # 开启服务
systemctl enable iptables  # 设置 iptables 开机启动
iptables -F # 清空 filter 表
iptables -X # 清空 filter 表自定义链
iptables -t nat -F # 清空 nat 表
iptables -t nat -X # 清空 nat 表自定义链

7.2 配置 NAT 规则

iptables -t nat -A POSTROUTING -o vlan1 -s 192.168.200.0/24 -j MASQUERADE # 开启主人网络到 WAN 的 PAT 转换
iptables -t nat -A POSTROUTING -o vlan1 -s 192.168.201.0/24 -j MASQUERADE # 开启客人网络 LAN 到 WAN 的 PAT 转换

7.3 配置防火墙规则

7.3.1 接口间转发规则

iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许已建立的连接
iptables -A FORWARD -i vlan2 -o vlan1 -j ACCEPT # 允许主人网络访问 WAN
iptables -A FORWARD -i vlan3 -o vlan1 -j ACCEPT # 允许客人网络访问 WAN
iptables -P FORWARD DROP    # 禁止其它转发

7.3.2 本机传入服务规则

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许已建立的连接
iptables -A INPUT -i lo -j ACCEPT # 允许本地接口所有传入连接
iptables -A INPUT -i vlan2 -p tcp --syn -m state --state NEW -m multiport --dports 22,53,80,443,1080,1081 -j ACCEPT # 允许主人网络发起的 SSH、DNS、HTTP、HTTPS、「双 S」连接
iptables -A INPUT -i vlan2 -p udp -m state --state NEW -m multiport --dports 53,67 -j ACCEPT # 允许主人网络发起的 DNS, DHCP 连接
iptables -A INPUT -i vlan3 -p udp -m state --state NEW -m multiport --dports 53,67 -j ACCEPT # 允许客人网络发起的 DNS, DHCP 连接
iptables -P INPUT DROP  # 禁止其它传入连接

7.3.3 本机传出服务规则

iptables -P OUTPUT ACCEPT   # 允许所有传出服务

7.4 配置透明代理

7.4.1 建立「双 S」专用链

iptables -t nat -N DUAL_S

7.4.2 把主人网络的所有 TCP 数据包送入「双 S」链中

iptables -t nat -A PREROUTING -i vlan2 -s 192.168.200.0/24 -p tcp -j DUAL_S

7.4.3 目的地址为「双 S」服务器、局域网、组播以及大陆 IP 不走「双 S」

iptables -t nat -A DUAL_S -d <「双 S」服务器 IP 地址> -j RETURN # 「双 S」服务器 IP 不走双 S
iptables -t nat -A DUAL_S -d 0.0.0.0/8 -j RETURN # 内网 IP 不走「双 S」,下同
iptables -t nat -A DUAL_S -d 10.0.0.0/8 -j RETURN
iptables -t nat -A DUAL_S -d 100.64.0.0/10 -j RETURN
iptables -t nat -A DUAL_S -d 127.0.0.0/8 -j RETURN
iptables -t nat -A DUAL_S -d 169.254.0.0/16 -j RETURN
iptables -t nat -A DUAL_S -d 172.16.0.0/12 -j RETURN
iptables -t nat -A DUAL_S -d 192.168.0.0/16 -j RETURN
iptables -t nat -A DUAL_S -d 224.0.0.0/4 -j RETURN # 组播 IP 不走「双 S」,下同
iptables -t nat -A DUAL_S -d 240.0.0.0/4 -j RETURN
iptables -t nat -A DUAL_S -p tcp -m set --match-set china_ip dst -j RETURN # 大陆 IP 不走「双 S」

7.4.4 其它 TCP 数据包一律走「双 S」

iptables -t nat -A DUAL_S -p tcp -j REDIRECT --to-ports 1081 # 其他 IP 全部走「双 S」

7.5 保存 iptables 设置

iptables-save > /etc/sysconfig/iptables


八、总结

该方案可以达到预期效果,但是仍有不完善的地方。

第一是没有在服务器上设置 QoS 来限制客人网络的网速(后来在交换机上设定了)。

第二是「可能被污染的域名列表」和「大陆 IP 地址集」无法实现自动更新。

不过现在就先这么用着吧,哈哈。

 

作者:海天启航
链接:https://www.jianshu.com/p/1265004c2922
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。