7

Ubuntu 软路由(篇二):v2ray 与透明(全局)代理

 2 years ago
source link: https://ppzz.github.io/posts/5393/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Ubuntu 软路由(篇二):v2ray 与透明(全局)代理

发表于 2020-06-07 分类于 LinuxRouter Valine: 0 本文字数: 6.8k 阅读时长 ≈ 6 分钟

如何在路由器上配置全局透明代理,以免被防火墙误伤。


接上一篇:Ubuntu 软路由(篇一):配置基于 ubuntu 的软路由

最早的时候,我使用了 shadowsocks 为基础的端口转发方案,但是配置复杂且不稳定。
这里使用的是 V2Ray + iptables 的转发方案。实际上由于 V2ray 支持路由,做网络的分流会方便很多,也更容易管理。

安装、配置 V2Ray

下载解压稳定的 v2ray 文件到安装目录,我这里用的是 /home/ubuntu/app/install/v2ray。为了获取稳定的新版本,我使用的是从 github 仓库下载的最后一版,仓库地址

cd /home/ubuntu/app/install
wget 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 :

├── config.json
├── geoip.dat
├── geosite.dat
├── systemd
│   └── system
│   ├── v2ray.service
│   └── [email protected]
├── v2ctl
├── v2ray
├── vpoint_socks_vmess.json
└── vpoint_vmess_freedom.json

接下来准备 systemd 的服务注册文件(用于将 v2ray 注册称一个服务以便自启动),
修改文件 /home/ubuntu/app/install/v2ray/systemd/system/v2ray.service, 原内容如下:

[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

有两处需要修改:

# ExecStart... 启动命令,修改启动文件位置、配置文件位置:
ExecStart=/home/ubuntu/app/install/v2ray/v2ray -config /home/ubuntu/app/install/v2ray/config.json

接下来将 v2ray 注册到 systemd,
(这里每次修改 service 文件之后都需要重新执行这个操作)

# 将service文件复制到系统的service文件存放位置
cp /home/ubuntu/app/install/v2ray/systemd/system/v2ray.service /etc/systemd/system/v2ray.service
# 更新service目录
sudo systemctl daemon-reload
# 启动v2ray
sudo systemctl start v2ray.service

查看 v2ray 运行状态:

sudo systemctl status v2ray.service

如下 log,当 Active 状态是 active 时,启动完成。

● 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

log:
access: /dev/null # 输出到空设备(丢弃),留空时将输出到 stdout
error: /home/ubuntu/app/log/v2ray/error.log # 留空时将输出到 stdout
logLevel: warning # debug|info|warning|error|none # 默认waring
inbounds: 入口
- tag: in_transparent # dokodemo-door 协议的inbound,用于透明代理流量
port: 1081 # 使用环境变量: env:MY_V2RAY_PORT
listen: 192.68.1.1 # 默认 0.0.0.0
protocol: dokodemo-door # blackhole|dokodemo-door|freedom|http|shadowsocks|socks|vmess
settings: # 具体的配置内容,视协议而定
network: tcp,udp
followRedirect: true
sniffing: # 探测流量,根据目的地址重制连接的目标
enabled: true
destOverride:
- http
- tls
streamSettings: # 底层传输配置,优先于全局的传输配置
sockopt:
tproxy: redirect
outbounds: # rules没有匹配到的流量默认走第一个outbound
- 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 # 默认tcp, tcp|kcp|ws|http|domainsocket,
sockopt:
mark: 0 # 非0时,在传出连接上标记 SO_MARK
tcpFastOpen: false
mux: # 用于在一条TCP数据连接上承载多条逻辑TCP链路,可以加速握手
enabled: true
concurrency: 4 # 默认8,范围:[1,1024],-1 表示加载Mux模块
routing:
domainStrategy: IPIfNonMatch
rules:
- type: field # 通过域名匹配国外流量: 常用的网站集合
domain:
- geosite:google
- geosite:facebook
- geosite:geolocation-!cn
outboundTag: *my_server_tag
- type: field # 通过域名匹配国外流量:自定义域名
domain: # 可以添加自己的域名:
- firecore.com # infuse 官网
- thetvdb.com # jellyfin 刷新元数据用
- themoviedb.org # jellyfin 刷新元数据用
- omdbapi.com # jellyfin 刷新元数据用
outboundTag: *my_server_tag
transport: # 传输设置,暂留空
policy: # 本地策略,暂留空

之后重启 v2ray 即可生效: sudo systemctl restart v2ray.service

配置 iptables

v2ray 已经运行起来,还需要将路由器收到的流量转发至 v2ray 监听的端口,让 v2ray 来接管需要代理的流量:

这里用一条明叫 V2RAY 的链来过滤需要被接管的流量,过滤不通过的流量会按照默认规则路由,不会走到 V2ray:

# 首先清空这条链(不存在会报错)
sudo iptables -t nat -F V2RAY
# 新建链
sudo iptables -t nat -N V2RAY

# 私有IP处理,RETURN: 过滤不通过,返回
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

# 其他不想要代理的IP:
# 这里一定需要将代理服务器的IP加进来(如果服务器是域名参考后面的说明):
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

# 需要代理的流量转发至V2ray的端口:1081,以下两行分别设置通过单个IP匹配、通过网络号匹配:
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 V2RAY -p tcp -j REDIRECT --to-ports 1081

# 将 POSTROUTING & OUTPUT 链的流量转发到V2RAY,具体只是搜索:iptable三表五链
sudo iptables -t nat -A PREROUTING -p tcp -j V2RAY
sudo iptables -t nat -A OUTPUT -p tcp -j V2RAY

备份修改后的 iptables

sudo /bin/bash /home/root/myipset.bash backup

具体参考上一篇 blog.

至此,被代理的主机已经可以无感穿过防火墙了。

iptables 规则过滤域名

iptables 仅能够过滤 IP,但是可以通过曲线救国手段过滤某些域名。
这个曲线救国的工具就是 ipset ubuntu 默认不带,需要先安装:

sudo apt-get install ipset -y

# 创建一个ipset(本质就是一个ip的列表)
sudo ipset create my-v2ray-ip-list hash:ip

编辑 dnsmasq 的配置文件:sudo vim /etc/dnsmasq.conf
追加写入:

# 用于将域名 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 文件,内容如下:

[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 内容如下,

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:

sudo systemctl daemon-reload # systemd刷新service文件
sudo systemctl enable myipset # 启用开机自启动 myipset
sudo systemctl start myipset # 运行 myipset

重新开关机之后也可以正常运行了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK