透明代理的旁路由虚拟网关
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
dnomd343 668548bb0a feat: custom log level 3 years ago
Dockerfile fix: env asset path of xray 3 years ago
LICENSE docs: LICENSE 3 years ago
README.md docs: more docker mirror registry, add examples 3 years ago
asset.sh fix: shell format 3 years ago
load.sh feat: custom log level 3 years ago
tproxy.sh docs: README.md 3 years ago

README.md

TProxy

容器化的旁路由透明代理工具,使用Xray处理TProxy流量,实现独立MAC与IP地址的虚拟化代理网关,支持 amd64i386arm64armv7 多种CPU架构,可代理全部TCP和UDP流量。

TProxy使用Docker容器化部署,在Docker HubGithub Package可以查看已构建的镜像。

镜像获取

Docker镜像建议拉取 latest 版本,如果需要特定版本镜像,拉取时指定tag为版本号即可。

# latest版本
shell> docker pull dnomd343/tproxy

# 指定版本
shell> docker pull dnomd343/tproxy:v1.1

TProxy可以从多个镜像源拉取,其数据完全相同,国内用户建议首选阿里云镜像。

# Docker Hub
shell> docker pull docker.io/dnomd343/tproxy

# Github Package
shell> docker pull ghcr.io/dnomd343/tproxy

# 阿里云个人镜像
shell> docker pull registry.cn-shenzhen.aliyuncs.com/dnomd343/tproxy

开始部署

首先开启网卡混杂模式

shell> ip link set eth0 promisc on

创建 macvlan 网络

# 此处网段与网关信息需按实际网络指定
shell> docker network create -d macvlan \
--subnet=192.168.2.0/24 \
--gateway=192.168.2.1 \
-o parent=eth0 macvlan

选择一个目录存储数据,此处使用 /etc/scutweb

shell> mkdir /etc/scutweb
shell> cd /etc/scutweb
shell> vim custom.sh

custom.sh 将在容器启动时首先执行,可用于指定容器静态IP与主路由网关地址

# 指定网关为192.168.2.1,容器IP为192.168.2.2
ip addr flush dev eth0
ip addr add 192.168.2.2/24 brd 192.168.2.255 dev eth0
ip route add default via 192.168.2.1

由于TProxy只代理传输层TCP与UDP以上的流量,网络层及以下其他数据包将不被处理,其中最常见的是ICMP数据包,表现为ping流量不走代理。但可以在 custom.sh 中添加以下命令,回应所有发往外网的ICMP数据包,表现为ping成功且延迟为内网访问时间(ICMP数据包实际未到达,使用NAT方式假冒远程主机返回到达信息)

# DNAT目标指定为自身IP地址
iptables -t nat -N FAKE_PING
iptables -t nat -A FAKE_PING -j DNAT --to-destination 192.168.2.2
iptables -t nat -A PREROUTING -i eth0 -p icmp -j FAKE_PING

启动容器,此处映射时间与时区信息到容器中,可以与宿主机进行同步(容器内默认为UTC零时区),用于日志时间记录

# 容器名称和存储目录可自行指定
shell> docker run --restart always \
--name scutweb \
--network macvlan \
--privileged -d \
--volume /etc/scutweb/:/etc/xray/expose/ \
--volume /etc/timezone:/etc/timezone:ro \
--volume /etc/localtime:/etc/localtime:ro \
dnomd343/tproxy
# 此处为DockerHub镜像源,可按上文链接替换为其他源

使用以下命令查看容器运行状态

shell> docker ps -a

容器成功运行以后,将会在存储目录下生成多个文件和文件夹

  • log:文件夹,存储代理流量日志

  • segment:文件夹,存储不代理的网段信息

  • outbounds.json:指定流量出口信息

  • routeing.json:指定流量路由信息

outbounds.json 默认配置流量转发给网关,需要用户手动配置为上游接口,具体语法见Xray文档

{
  "outbounds": [
    {
      "tag": "node",
      "protocol": "freedom"
    }
  ]
}

routing.json 默认配置将全部流量交由 node 接口,即 outbounds.json 中的 freedom 出口,具体语法见Xray文档

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "proxy"
        ],
        "outboundTag": "node"
      },
      {
        "type": "field",
        "network": "tcp,udp"
        "outboundTag": "node"
      }
    ]
  }
}

dns.json 指定路由匹配时的DNS服务器,具体语法见Xray文档

{
  "dns": {
    "servers": [
      "223.5.5.5",
      "119.29.29.29"
    ]
  }
}

segment 文件夹下默认有 ipv4ipv6 两个文件,其中存储不代理的网段信息,建议绕过内网地址、本地回环地址、链路本地地址、组播地址等网段

# IPv4与IPv6均默认绕过组播地址
shell> cat /etc/scutweb/segment/ipv4
127.0.0.0/8
169.254.0.0/16
224.0.0.0/3
shell> cat /etc/scutweb/segment/ipv6
::1/128
FC00::/7
FE80::/10
FF00::/8

配置完成后重启容器生效

shell> docker restart scutweb

此时宿主机无法与macvlan网络直接连接,需要手动配置桥接,这里以Debian系Linux发行版为例

shell> vim /etc/network/interfaces

补充如下配置

# 具体网络信息需要按实际情况指定
auto eth0
iface eth0 inet manual

auto macvlan
iface macvlan inet static
  address 192.168.2.34
  netmask 255.255.255.0
  gateway 192.168.2.2
  dns-nameservers 192.168.2.3
  pre-up ip link add macvlan link eth0 type macvlan mode bridge
  post-down ip link del macvlan link eth0 type macvlan mode bridge

重启宿主机网络生效(重启宿主机亦可)

shell> /etc/init.d/networking restart
[ ok ] Restarting networking (via systemctl): networking.service.

配置完成后,TProxy容器的IP地址可视为旁路由IP,需要使用TProxy代理的设备修改其网关为该IP地址,若想让内网全部设备均可使用,则需修改路由器DHCP设置,将网关指向容器IP(仅对动态IP地址设备生效,配置过静态IP的设备仍需手动修改)

实例演示

示例1-全局科学上网

代理全部流量并进行分流,国内流量直连,国外流量走科学上网节点

初始化命令中指定容器IP地址

# custom.sh
ip addr flush dev eth0
ip addr add 192.168.2.4/24 brd 192.168.2.255 dev eth0
ip route add default via 192.168.2.2

绕过内网IP地址,添加 192.168.2.0/24 网段

# segment/ipv4
127.0.0.0/8
169.254.0.0/16
192.168.2.0/24
224.0.0.0/3

此处将DNS指向本地的无污染ClearDNS服务,如果未部署该服务,修改为 8.8.8.8 即可(Xray会将其重新路由至国外节点,不存在污染问题)

# dns.json
{
  "dns": {
    "servers": [
      "192.168.2.3"
    ]
  }
}

可以配置多个服务节点负载均衡,提高科学上网速度,这里设置了三个VLESS+XTLS节点。

# outbounds.json
{
  "outbounds": [
    {
      "tag": "proxy01",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "···",
            "port": 443,
            "users": [
              {
                "id": "···",
                "encryption": "none",
                "flow": "xtls-rprx-direct"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "xtls",
        "xtlsSettings": {
          "allowInsecure": false,
          "serverName": "···"
        }
      }
    },
    {
      "tag": "proxy02",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "···",
            "port": 443,
            "users": [
              {
                "id": "···",
                "encryption": "none",
                "flow": "xtls-rprx-direct"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "xtls",
        "xtlsSettings": {
          "allowInsecure": false,
          "serverName": "···"
        }
      }
    },
    {
      "tag": "proxy03",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "···",
            "port": 443,
            "users": [
              {
                "id": "···",
                "encryption": "none",
                "flow": "xtls-rprx-direct"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "xtls",
        "xtlsSettings": {
          "allowInsecure": false,
          "serverName": "···"
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}

在路由中配置分流与负载均衡,其中还开启了广告拦截功能

# routing.json
{
  "routing": {
    "domainStrategy": "IPOnDemand",
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "proxy"
        ],
        "balancerTag": "balancer"
      },
      {
        "type": "field",
        "domain": [
          "geosite:category-ads-all"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private",
          "geoip:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "balancerTag": "balancer"
      }
    ],
    "balancers": [
      {
        "tag": "balancer",
        "selector": [
          "proxy"
        ]
      }
    ]
  }
}

配置完成后重启容器即可使用

示例2-校园网绕过认证

部分校园网存在TCP/53或UDP/53端口无认证漏洞,可将全部流量代理并转发到个人服务器上,实现免认证、无限速的上网

初始化命令中指定容器IP地址,同时模拟外网ICMP数据包响应(否则所有ping均为超时)

# custom.sh
ip addr flush dev eth0
ip addr add 192.168.2.2/24 brd 192.168.2.255 dev eth0
ip route add default via 192.168.2.1
iptables -t nat -N SCUT_PING
iptables -t nat -A SCUT_PING -j DNAT --to-destination 192.168.2.2
iptables -t nat -A PREROUTING -i eth0 -p icmp -j SCUT_PING

绕过内网IP地址,添加 192.168.2.0/24 网段

# segment/ipv4
127.0.0.0/8
169.254.0.0/16
192.168.2.0/24
224.0.0.0/3

此时所有流量将被代理,不存在域名分流需求,因此无需设置DNS服务器

# dns.json
{
  "dns": {}
}

这里配置了三个节点,平时使用一台即可,其他两台作为备用容灾

# outbounds.json
{
  "outbounds": [
    {
      "tag": "nodeA",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "···",
            "port": 53,
            "users": [
              {
                "id": "···",
                "encryption": "none",
                "flow": "xtls-rprx-direct"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "xtls",
        "xtlsSettings": {
          "allowInsecure": false,
          "serverName": "···"
        }
      }
    },
    {
      "tag": "nodeB",
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "···",
            "port": 53,
            "users": [
              {
                "id": "···",
                "alterId": 0,
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "allowInsecure": false,
          "serverName": "···"
        }
      }
    },
    {
      "tag": "nodeC",
      "protocol": "shadowsocks",
      "settings": {
        "servers": [
          {
            "address": "···",
            "method": "aes-256-gcm",
            "ota": false,
            "password": "···",
            "port": 53
          }
        ]
      },
      "streamSettings": {
        "network": "tcp"
      }
    }
  ]
}

路由核心接管全部流量并转发给 nodeA 节点

# routing.json
{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "nodeA"
      }
    ]
  }
}

配置完成后重启容器即可使用

开发相关

预设接口

  • Socks5代理: 1080端口,支持UDP,无授权,标志为 socks

  • HTTP代理: 1081端口,无授权,标志为 http

  • 全局Socks5代理: 10808端口,支持UDP,无授权,标志为 proxy

容器构建

本地构建

# 克隆仓库
shell> git clone https://github.com/dnomd343/TProxy.git
shell> cd TProxy
# 构建镜像
shell> docker build -t tproxy .

交叉构建

# 构建并推送至Docker Hub
shell> docker buildx build -t dnomd343/tproxy --platform="linux/amd64,linux/arm64,linux/386,linux/arm/v7" https://github.com/dnomd343/TProxy.git#master --push

许可证

MIT ©2021 @dnomd343