如何在路由器上配置全局透明代理,以免被防火墙误伤。
接上一篇:Ubuntu 软路由(篇一):配置基于 ubuntu 的软路由
最早的时候,我使用了 shadowsocks 为基础的端口转发方案,但是配置复杂且不稳定。 这里使用的是 V2Ray + iptables 的转发方案。实际上由于 V2ray 支持路由,做网络的分流会方便很多,也更容易管理。
安装、配置 V2Ray 安装 下载解压稳定的 v2ray 文件到安装目录,我这里用的是 /home/ubuntu/app/install/v2ray
。为了获取稳定的新版本,我使用的是从 github 仓库下载的最后一版,仓库地址
1 2 3 cd /home/ubuntu/app/installwget https://github.com/v2fly/v2ray-core/releases/download/v4.33.0/v2ray-linux-64.zip unzip -d v2ray v2ray-linux-64.zip
解压之后目录内容如下:
/home/ubuntu/app/install/v2ray
:
1 2 3 4 5 6 7 8 9 10 11 ├── config.json ├── geoip.dat ├── geosite.dat ├── systemd │ └── system │ ├── v2ray.service │ └── v2ray@.service ├── v2ctl ├── v2ray ├── vpoint_socks_vmess.json └── vpoint_vmess_freedom.json
接下来准备 systemd 的服务注册文件(用于将 v2ray 注册称一个服务以便自启动), 修改文件 /home/ubuntu/app/install/v2ray/systemd/system/v2ray.service
, 原内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [Unit] Description=V2Ray Service Documentation=https://www.v2fly.org/ After=network.target nss-lookup.target [Service] User=nobody CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE NoNewPrivileges=true ExecStart=/usr/local/bin/v2ray -config /usr/local/etc/v2ray/config.json Restart=on-failure RestartPreventExitStatus=23 [Install] WantedBy=multi-user.target
有两处需要修改:
1 2 ExecStart=/home/ubuntu/app/install/v2ray/v2ray -config /home/ubuntu/app/install/v2ray/config.json
接下来将 v2ray 注册到 systemd, (这里每次修改 service 文件之后都需要重新执行这个操作)
1 2 3 4 5 6 cp /home/ubuntu/app/install/v2ray/systemd/system/v2ray.service /etc/systemd/system/v2ray.service sudo systemctl daemon-reload sudo systemctl start v2ray.service
查看 v2ray 运行状态:
sudo systemctl status v2ray.service
如下 log,当 Active 状态是 active 时,启动完成。
1 2 3 4 5 6 7 8 9 10 ● v2ray.service - V2Ray Service Loaded: loaded (/etc/systemd/system/v2ray.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2021-03-15 00:53:22 CST; 4h 5min ago Docs: https://www.v2ray.com/ https://www.v2fly.org/ Main PID: 56320 (v2ray) Tasks: 11 (limit: 4501) Memory: 27.7M CGroup: /system.slice/v2ray.service └─56320 /home/ubuntu/app/install/v2ray/v2ray -c /home/ubuntu/app/v2ray.json
配置 v2ray 记录一下简要的配置备忘: 为了可读性和维护性,我用了 yaml 记录配置文件。v2ray 实际并不支持 yaml 格式的配置文件,将 yaml 先转成 json 才能够正常使用。
yaml 转 json: yq -j eval my_config.yaml > my_config.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 log: access: /dev/null error: /home/ubuntu/app/log/v2ray/error.log logLevel: warning inbounds: 入口 - tag: in_transparent port: 1081 listen: 192.68 .1 .1 protocol: dokodemo-door settings: network: tcp,udp followRedirect: true sniffing: enabled: true destOverride: - http - tls streamSettings: sockopt: tproxy: redirect outbounds: - tag: out_direct protocol: freedom - tag: &my_server_tag my_server_tag protocol: vmess sendThrough: 0.0 .0 .0 settings: vnext: - address: my_server.com port: 2048 users: - id: aaaaaaaa-aaaa-aaaa-aaaaa-aaaaaaaaaaaaa alterId: 64 streamSettings: network: tcp sockopt: mark: 0 tcpFastOpen: false mux: enabled: true concurrency: 4 routing: domainStrategy: IPIfNonMatch rules: - type: field domain: - geosite:google - geosite:facebook - geosite:geolocation-!cn outboundTag: *my_server_tag - type: field domain: - firecore.com - thetvdb.com - themoviedb.org - omdbapi.com outboundTag: *my_server_tag transport: policy:
之后重启 v2ray 即可生效: sudo systemctl restart v2ray.service
。
配置 iptables v2ray 已经运行起来,还需要将路由器收到的流量转发至 v2ray 监听的端口,让 v2ray 来接管需要代理的流量:
这里用一条明叫 V2RAY 的链来过滤需要被接管的流量,过滤不通过的流量会按照默认规则路由,不会走到 V2ray:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 sudo iptables -t nat -F V2RAY sudo iptables -t nat -N V2RAY sudo iptables -t nat -A V2RAY -d 0/8 -j RETURN sudo iptables -t nat -A V2RAY -d 10/8 -j RETURN sudo iptables -t nat -A V2RAY -d 127/8 -j RETURN sudo iptables -t nat -A V2RAY -d 169.254/16 -j RETURN sudo iptables -t nat -A V2RAY -d 172.16/12 -j RETURN sudo iptables -t nat -A V2RAY -d 192.168/16 -j RETURN sudo iptables -t nat -A V2RAY -d 224/4 -j RETURN sudo iptables -t nat -A V2RAY -d 240/4 -j RETURN sudo iptables -t nat -A V2RAY -d 255.255.255/32 -j RETURN sudo iptables -t nat -A V2RAY -s my_v2ray_remote_server_ip -j RETURN sudo iptables -t nat -A V2RAY -s 10.10.20.11 -j RETURN sudo iptables -t nat -A V2RAY -s 10.10.20.12 -j RETURN sudo iptables -t nat -A V2RAY -s 10.10.21.0/24 -p tcp -j REDIRECT --to-ports 1081 sudo iptables -t nat -A V2RAY -s 10.10.22.2 -p tcp -j REDIRECT --to-ports 1081 sudo iptables -t nat -A PREROUTING -p tcp -j V2RAY sudo iptables -t nat -A OUTPUT -p tcp -j V2RAY
备份修改后的 iptables
1 sudo /bin/bash /home/root/myipset.bash backup
具体参考上一篇 blog.
至此,被代理的主机已经可以无感穿过防火墙了。
iptables 规则过滤域名 iptables 仅能够过滤 IP,但是可以通过曲线救国手段过滤某些域名。 这个曲线救国的工具就是 ipset ubuntu 默认不带,需要先安装:
1 2 3 4 sudo apt-get install ipset -y sudo ipset create my-v2ray-ip-list hash :ip
编辑 dnsmasq 的配置文件:sudo vim /etc/dnsmasq.conf
追加写入:
1 2 3 # 用于将域名 v2ray_server_host 匹配到的域名的ip写入 my-v2ray-ip-list 中 # 距离 baidu.com 可以匹配到 baidu.com, pan.baidu.com 等。 ipset=/v2ray_server_host/my-v2ray-ip-list
之后重启 dnsmasq 服务即可生效 systemctl restart dnsmasq.service
。
持久化 ipset 的配置 由于 ipset 关机会丢失,这里为它写一个自动保存和加载的脚本,参考上一篇中 iptables 的脚本。
service 文件路径 /etc/systemd/system/myipset.service 处理 ipset 的脚本路径 /home/root/ipset.bash ipset 备份文件保存路径 /home/root/backup.ipset.ipv4
创建文件 service 文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 [Unit] Description=backup ipset when shutdown & restore ipset when boot Before=myiptables.service [Service] Type=oneshot RemainAfterExit=true ExecStart=/bin/bash /home/root/ipset.bash restore ExecStop=/bin/bash /home/root/ipset.bash backup [Install] WantedBy=multi-user.target
上面用到的保存 ipset 数据的脚本 ipset.bash 内容如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 default_backup_file="/home/root/backup.ipset.ipv4" echo "$default_backup_file " action=$1 backup_file=${2:-$default_backup_file } if [ ! "${backup_file} " ]; then echo "param 2 error: should not empty." exit 1 fi if [ "$action " == 'restore' ]; then /sbin/ipset restore <"${backup_file} " exit 0 fi if [ "$action " == 'backup' ]; then ensure_dir_exist "$(dirname "$backup_file " ) " /sbin/ipset save >"$backup_file " exit 0 fi echo backup_file path: "${default_backup_file} " echo "user param: 'backup' or 'restore'" exit 1
保存好脚本 之后手动保存一次 ipset 的数据: ipset save > /home/root/backup.ipset.ipv4 接下来开始激活 ipset.service:
1 2 3 4 sudo systemctl daemon-reload sudo systemctl enable myipset sudo systemctl start myipset
重新开关机之后也可以正常运行了。