Ubuntu Linux 部署 v2ray 软路由做透明代理

就当是笔记啦 ╮( ̄▽ ̄"")╭ 感谢 Project V 及其所有 contributors

下面的脚本唯一 assumed 的是服务器那边 v2ray 开启了 mKCP,具体 assumed 的 mKCP 配置如下

"streamSettings": {
    "tlsSettings": {
        "allowInsecure": true
    },
    "security": "none",
    "kcpSettings": {
        "header": {
            "type": "srtp"
        },
        "mtu": 1350,
        "congestion": true,
        "tti": 20,
        "uplinkCapacity": 100,
        "writeBufferSize": 1,
        "readBufferSize": 1,
        "downlinkCapacity": 200
    },
    "network": "kcp"
},

要使用的话,要么改一下自己服务器那边的配置,要么就改一下下面脚本中高亮的部分即可~(总之保持一致就可以( ´▽`)

用法的话也很简单了,复制下面所有代码到 v2ray-tproxy.sh (或者别的喜欢的文件名也行233333,之后自己替换一下下面的命令,让文件名跟你取的保持一致即可),

假设你的内网网段是 10.0.1.0/24,v2ray 服务器 IP 是 1.2.3.4,端口是 12345,以及用户 ID 是 12345678-90ab-cdef-1234-567890abcdef 的话,那就执行如下命令~

# 以 root 用户执行下面所有的操作
sudo su
# 从官方的脚本安装 v2ray
bash <(curl -L -s https://install.direct/go.sh)
# 复制后一段的代码到 ./v2ray-tproxy.sh
# 然后赋予可执行权限 ./v2ray-tproxy.sh
chmod +x ./v2ray-tproxy.sh
# 设置 v2ray 透明代理
./v2ray-tproxy.sh '10.0.1.0/24' '1.2.3.4' '12345' '12345678-90ab-cdef-1234-567890abcdef'

v2ray-tproxy.sh 的内容如下~

#!/bin/bash
# Credits to v2ray project
# This script is written byRyza <[data deleted]>
# And this script is based on https://toutyrater.github.io/app/tproxy.html, massive thanks
#
# Usage:
# sudo ./v2ray-tproxy.sh CIDR局域网网段 服务器IP 服务器端口 用户ID
#
# Example:
# sudo ./v2ray-tproxy.sh '10.0.1.0/24' '1.2.3.4' '12345' '12345678-90ab-cdef-1234-567890abcdef'

function deploy_iptables_rules {
    echo "[INFO] Deploying iptables rules"

    ip rule add fwmark 1 table 100
    ip route add local 0.0.0.0/0 dev lo table 100

    iptables -t mangle -N V2RAY
    iptables -t mangle -A V2RAY -d 127.0.0.1/32 -j RETURN
    iptables -t mangle -A V2RAY -d 224.0.0.0/4 -j RETURN
    iptables -t mangle -A V2RAY -d 255.255.255.255/32 -j RETURN

    # 直连局域网,避免 V2Ray 无法启动时无法连网关的 SSH
    iptables -t mangle -A V2RAY -d "$1" -p tcp -j RETURN
    # 直连局域网,53 端口除外, 因为要使用 V2Ray  
    iptables -t mangle -A V2RAY -d "$1" -p udp ! --dport 53 -j RETURN 
    #  UDP 打标记 1,转发至 12345 端口
    iptables -t mangle -A V2RAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1
    #  TCP 打标记 1,转发至 12345 端口
    iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1
    # 应用规则
    iptables -t mangle -A PREROUTING -j V2RAY

    iptables -t mangle -N V2RAY_MASK
    iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
    iptables -t mangle -A V2RAY_MASK -d 255.255.255.255/32 -j RETURN
    # 直连局域网
    iptables -t mangle -A V2RAY_MASK -d "$1" -p tcp -j RETURN
    # 直连局域网,53 端口除外, 因为要使用 V2Ray  DNS
    iptables -t mangle -A V2RAY_MASK -d "$1" -p udp ! --dport 53 -j RETURN
    # 直连 SO_MARK  0xff 的流量 (0xff  16 进制数,数值上等同与上面 V2Ray 配置的 255), 此规则目的是避免代理本机(网关)流量出现回环问题
    iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff
    #  UDP 打标记,重路由
    iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1
    #  TCP 打标记,重路由
    iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1
    # 应用规则
    iptables -t mangle -A OUTPUT -j V2RAY_MASK
}

function dump_iptables_rules {
    echo "[INFO] Dumping added iptables rules to /etc/iptables/rules.v4"
    mkdir -p /etc/iptables && iptables-save > /etc/iptables/rules.v4
}

function set_autorestoring_iptables_rules_service {
    echo "[INFO] Adding systemd service for auto-restoring the added iptables rules"
    cat <<EOF >/etc/systemd/system/v2ray-iptables.service
[Unit]
Description=Tproxy rule
After=network.target
Wants=network.target

[Service]

Type=oneshot
ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; /sbin/iptables-restore /etc/iptables/rules.v4

[Install]
WantedBy=multi-user.target
EOF
    systemctl enable v2ray-iptables
}

function generate_v2ray_config {
    echo "[INFO] Generating v2ray config"
    cat <<EOF >/etc/v2ray/config.json
{
    "inbounds": [
        {
            "tag":"transparent",
            "port": 12345,
            "protocol": "dokodemo-door",
            "settings": {
                "network": "tcp,udp",
                "followRedirect": true
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls"
                ]
            },
            "streamSettings": {
                "sockopt": {
                    "tproxy": "tproxy"
                }
            }
        },
        {
            "listen": "0.0.0.0",
            "port": 1080, 
            "protocol": "socks",
            "sniffing": {
                "enabled": true,
                "destOverride": ["http", "tls"]
            },
            "settings": {
                "auth": "noauth"
            }
        },
        {
            "listen": "0.0.0.0",
            "protocol": "http",
            "settings": {
                "timeout": 360
            },
            "port": "1087"
        }
    ],
    "outbounds": [
        {
            "streamSettings": {
                "tlsSettings": {
                    "allowInsecure": true
                },
                "security": "none",
                "kcpSettings": {
                    "header": {
                        "type": "srtp"
                    },
                    "mtu": 1350,
                    "congestion": true,
                    "tti": 20,
                    "uplinkCapacity": 100,
                    "writeBufferSize": 1,
                    "readBufferSize": 1,
                    "downlinkCapacity": 200
                },
                "network": "kcp"
            },
            "tag": "proxy",
            "protocol": "vmess",
            "settings": {
                "vnext": [
                    {
                        "address": "$1",
                        "port": $2,
                        "users": [
                            {
                                "id": "$3",
                                "alterId": 64,
                                "level": 1,
                                "security": "auto"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "sockopt": {
                    "mark": 255
                }
            },
            "mux": {
                "enabled": false
            }
        },
        {
            "tag": "direct",
            "protocol": "freedom",
            "settings": {
                "domainStrategy": "UseIP"
            },
            "streamSettings": {
                "sockopt": {
                    "mark": 255
                }
            }      
        },
        {
            "tag": "block",
            "protocol": "blackhole",
            "settings": {
                "response": {
                    "type": "http"
                }
            }
        },
        {
            "tag": "dns-out",
            "protocol": "dns",
            "streamSettings": {
                "sockopt": {
                    "mark": 255
                }
            }  
        }
    ],
    "dns": {
        "servers": [
            "8.8.8.8",
            "1.1.1.1",
            "114.114.114.114",
            {
                "address": "223.5.5.5",
                "port": 53,
                "domains": [
                    "geosite:cn",
                    "ntp.org"
                ]
            }
        ]
    },
    "routing": {
        "domainStrategy": "IPOnDemand",
        "rules": [
            {
                "type": "field",
                "inboundTag": [
                    "transparent"
                ],
                "port": 53,
                "network": "udp",
                "outboundTag": "dns-out" 
            },
            {
                "type": "field",
                "inboundTag": [
                    "transparent"
                ],
                "port": 123,
                "network": "udp",
                "outboundTag": "direct" 
            },    
            {
                "type": "field", 
                "ip": [
                    "223.5.5.5",
                    "114.114.114.114"
                ],
                "outboundTag": "direct"
            },
            {
                "type": "field",
                "ip": [
                    "8.8.8.8",
                    "1.1.1.1"
                ],
                "outboundTag": "proxy"
            },
            {
                "type": "field", 
                "domain": [
                    "geosite:category-ads-all"
                ],
                "outboundTag": "block"
            },
            {
                "type": "field",
                "protocol":["bittorrent"], 
                "outboundTag": "direct"
            },
            {
                "type": "field", 
                "ip": [
                    "geoip:private",
                    "geoip:cn"
                ],
                "outboundTag": "direct"
            },
            {
                "type": "field", 
                "domain": [
                    "geosite:cn"
                ],
                "outboundTag": "direct"
            }
        ]
    }
}
EOF
}

function modify_num_of_max_open_files {
    echo "[INFO] Setting number of max open files to 1000000"
    sed -i 's/Status=23/Status=23\nLimitNPROC=500\nLimitNOFILE=1000000\n/' /etc/systemd/system/v2ray.service
}

function start_v2ray_transparent_proxy_service {
    echo "[INFO] Starting v2ray transparent proxy service"
    systemctl daemon-reload
    systemctl restart v2ray
}

function main {
    deploy_iptables_rules $1
    dump_iptables_rules
    set_autorestoring_iptables_rules_service
    generate_v2ray_config $2 $3 $4
    modify_num_of_max_open_files
    start_v2ray_transparent_proxy_service
}

# sudo ./v2ray-tproxy.sh '10.0.1.0/24' 1.2.3.4 12345 12345678-90ab-cdef-1234-567890abcdef
main $1 $2 $3 $4

2 thoughts on “Ubuntu Linux 部署 v2ray 软路由做透明代理”

  1. 想问一下您ubuntu本身的网络是怎么配置的。

    上述配置,在以下场景是OK的,我也测试了:

    Ubuntu Server 的eth0 用netplan 配置为 dhcp: true, eth0用网线接入上级路由器的lan口,上级路由器里开启dhcp,eth0自动获得ip地址(例如10.120.10.234这样的一个nat地址,但是可以上internet)。Ubuntu Server 的eth1 用netplan配置为固定ip,addresses: 192.168.2.1/24
    Ubuntu Server里装了dnsmasq,interface设置为eth1,dhcp-range设置为192.168.2.100到150,eth1用网线接到一个wifi路由器的wan口上,wifi路由器的wan口设置为dhcp获取ip(例如获得192.168.2.101)。 然后在您blog中脚本的基础上,增加了一条iptables规则:iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 这样所有连接到wifi路由器的客户机都可以通过这台ubuntu Server 透明代理后科学上网。

    但是场景发生一点点变化,Ubuntu Server 的eth0用网线直接接到光猫上,netplan中eth0 设置为 dhcp: no,然后用pppoeconf创建拨号,pppoeconf会自动创建一个ppp0的接口,拨号后获得一个ip地址(例如172.120.10.123)。其他部分不变,Ubuntu Server 的eth1 用netplan配置为固定ip,addresses: 192.168.2.1/24,Ubuntu Server里装了dnsmasq,interface设置为eth1,dhcp-range设置为192.168.2.100到150,eth1用网线接到一个wifi路由器的wan口上,wifi路由器的wan口设置为dhcp获取ip(例如获得192.168.2.101)。
    接下来,问题出现了:
    这时候将新增的iptables规则改为 iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE, 此时wifi路由器的客户机都能够正常上网(非科学)。然后开始手动执行您的脚本,v2ray的所有配置都不变,然后开始逐条执行iptables,一旦执行“ iptables -t mangle -A PREROUTING -j V2RAY” 这句, Ubuntu Server本身和wifi路由器下的所有客户端都不能正常访问网络。

    不知道问题出在哪里了。
    不知您是否有时间研究下

    1. 非常抱歉呢,这个场景我不是很确定的说,虽然是 CS 系的,但是个人在这一块的了解并不算太多呢_(:3」∠)_

      我这里的这个脚本是基于 https://toutyrater.github.io/app/tproxy.html 这个页面写的,然后根据我自己在实践的操作,增加了一些自动填充和修改文件的部分。您可以问问看这个脚本的原作者

Leave a Reply

Your email address will not be published. Required fields are marked *

4 × five =