From c4d8a4096a96de1c24dba3263fa506cf730000ee Mon Sep 17 00:00:00 2001 From: "ryan @archi" Date: Sat, 11 Feb 2023 19:42:03 +0300 Subject: [PATCH 1/6] Added an entry point interceptor --- Dockerfile | 5 ++++- entrypoint.sh | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 94fdad6..333eb03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,4 +15,7 @@ RUN set -ex \ && chmod +x /root/v2ray.sh \ && /root/v2ray.sh "${TARGETPLATFORM}" "${TAG}" -ENTRYPOINT ["/usr/bin/v2ray"] +COPY entrypoint.sh /root/entrypoint.sh +RUN chmod +x /root/entrypoint.sh + +ENTRYPOINT ["/root/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..41a025d --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/bin/v2ray "$@" \ No newline at end of file From 519ec2a377ed1f12e9443527fc65a63f9003e123 Mon Sep 17 00:00:00 2001 From: "ryan @archi" Date: Sat, 11 Feb 2023 19:42:56 +0300 Subject: [PATCH 2/6] Add the iptables package --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 333eb03..8af796c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ FROM --platform=${TARGETPLATFORM} alpine:latest LABEL maintainer="V2Fly Community " +RUN apk add iptables + WORKDIR /root ARG TARGETPLATFORM ARG TAG From a1e5be18a500b2a907d4b51d1de3b7fe3aa43a71 Mon Sep 17 00:00:00 2001 From: "ryan @archi" Date: Sun, 12 Feb 2023 02:13:32 +0300 Subject: [PATCH 3/6] Added the default values for the environment variables --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index 8af796c..5e0a655 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,4 +20,8 @@ RUN set -ex \ COPY entrypoint.sh /root/entrypoint.sh RUN chmod +x /root/entrypoint.sh +ENV TPROXY false +ENV DOKODEMO_DOOR_PORT 12345 +ENV BYPASS_SUBNETS "" + ENTRYPOINT ["/root/entrypoint.sh"] From cb5c4189746430ec1f8951c492d9d0955d73a7ae Mon Sep 17 00:00:00 2001 From: "ryan @archi" Date: Sun, 12 Feb 2023 02:14:41 +0300 Subject: [PATCH 4/6] Adding entrypoint shell file to the github workflow --- .github/workflows/docker-push.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml index cb61677..c1a2560 100644 --- a/.github/workflows/docker-push.yml +++ b/.github/workflows/docker-push.yml @@ -6,12 +6,14 @@ on: push: paths: - "v2ray.sh" + - "entrypoint.sh" - "Dockerfile" - ".github/workflows/docker-push.yml" pull_request: types: [opened, synchronize, reopened] paths: - "v2ray.sh" + - "entrypoint.sh" - "Dockerfile" - ".github/workflows/docker-push.yml" From a9f53003dd0b5ff5e31d2c51b3d86045c02d254e Mon Sep 17 00:00:00 2001 From: "ryan @archi" Date: Sun, 12 Feb 2023 02:15:23 +0300 Subject: [PATCH 5/6] Setting up the gateway iptables rules --- entrypoint.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/entrypoint.sh b/entrypoint.sh index 41a025d..829a36b 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,3 +1,72 @@ #!/bin/sh + +setupTProxy() { + + local docker_network="$(ip -o addr show dev eth0 | awk '$3 == "inet" {print $4}')" + local default_gateway=$(ip -4 route | grep 'default via' | awk '{print $3}') + local dokodemo_port=12345 + + if [[ $DOKODEMO_DOOR_PORT ]]; then + dokodemo_port=$DOKODEMO_DOOR_PORT + fi + + echo " +--- Setting up the gateway iptables rules ---- + dokodemo-door port: ${dokodemo_port} + Bypassed subnets: ${docker_network}, ${BYPASS_SUBNETS} + Default gateway: ${default_gateway} +Pay attention: This gateway handles the TCP and UDP requests. The Dokodemo-door doesn't support ICMP packets!" + + # Reference: https://guide.v2fly.org/app/tproxy.html#%E8%AE%BE%E7%BD%AE%E7%BD%91%E5%85%B3 + # Set policy routing + ip rule add fwmark 1 table 100 + ip route add local 0.0.0.0/0 dev lo table 100 + # Proxy LAN device + iptables -t mangle -N V2RAY + iptables -t mangle -A V2RAY -d 127.0.0.1/24 -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 + iptables -t mangle -A V2RAY -d ${docker_network} -p tcp -j RETURN # Directly connect to the LAN to avoid SSH that cannot connect to the gateway when V2Ray cannot be started. If you configure other network segments (such as 10.x.x.x, etc.), modify it to your own + iptables -t mangle -A V2RAY -d ${docker_network} -p udp ! --dport 53 -j RETURN # Directly connected to the LAN, except port 53 (because V2Ray's DNS is used) + if [[ $BYPASS_SUBNETS ]]; then + for subnet in ${BYPASS_SUBNETS//,/ }; do + iptables -t mangle -A V2RAY -d "$subnet" -p tcp -j RETURN + iptables -t mangle -A V2RAY -d "$subnet" -p udp ! --dport 53 -j RETURN + done + fi + iptables -t mangle -A V2RAY -j RETURN -m mark --mark 0xff # Directly connect to the traffic whose SO_MARK is 0xff (0xff is a hexadecimal number, which is equivalent to 255 in the above V2Ray configuration). The purpose of this rule is to solve the problem that v2ray takes up a lot of CPU(https://github.com/v2ray/v2ray-core/issues/2621) + iptables -t mangle -A V2RAY -p udp -j TPROXY --on-ip 127.0.0.1 --on-port ${dokodemo_port} --tproxy-mark 1 # Mark UDP as 1 and forward to port 12345 + iptables -t mangle -A V2RAY -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port ${dokodemo_port} --tproxy-mark 1 # Mark the TCP with 1 and forward it to port 12345 + iptables -t mangle -A PREROUTING -j V2RAY # application rules + + # proxy gateway native + 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 ${docker_network} -p tcp -j RETURN # Direct LAN + iptables -t mangle -A V2RAY_MASK -d ${docker_network} -p udp ! --dport 53 -j RETURN # Directly connected to LAN, except port 53 (because V2Ray's DNS is used) + if [[ $BYPASS_SUBNETS ]]; then + for subnet in ${BYPASS_SUBNETS//,/ }; do + iptables -t mangle -A V2RAY_MASK -d "$subnet" -p tcp -j RETURN # Direct LAN + iptables -t mangle -A V2RAY_MASK -d "$subnet" -p udp ! --dport 53 -j RETURN # Directly connected to LAN, except port 53 (because V2Ray's DNS is used) + done + fi + iptables -t mangle -A V2RAY_MASK -j RETURN -m mark --mark 0xff # Directly connect to traffic whose SO_MARK is 0xff (0xff is a hexadecimal number, which is equivalent to 255 in the above V2Ray configuration). The purpose of this rule is to avoid the loopback problem of proxy local (gateway) traffic + iptables -t mangle -A V2RAY_MASK -p udp -j MARK --set-mark 1 # Mark UDP, reroute + iptables -t mangle -A V2RAY_MASK -p tcp -j MARK --set-mark 1 # Mark TCP, reroute + iptables -t mangle -A OUTPUT -j V2RAY_MASK # application rules + + # Create a new DIVERT rule to prevent existing connected packets from passing through TPROXY twice, theoretically, there is a certain performance improvement + iptables -t mangle -N DIVERT + iptables -t mangle -A DIVERT -j MARK --set-mark 1 + iptables -t mangle -A DIVERT -j ACCEPT + iptables -t mangle -I PREROUTING -p tcp -m socket -j DIVERT +} + + +if [[ "$TPROXY" = "true" ]]; then + setupTProxy & +fi + /usr/bin/v2ray "$@" \ No newline at end of file From 2997afb7b533c0dec69bd94fddf8c02ab24f536d Mon Sep 17 00:00:00 2001 From: "ryan @archi" Date: Sun, 12 Feb 2023 03:54:09 +0300 Subject: [PATCH 6/6] Adding a definition of gateway mode --- README.md | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/README.md b/README.md index 07f8d6c..6cd754a 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,203 @@ docker run --rm v2fly/v2fly-core help docker run --name v2ray v2fly/v2fly-core $v2ray_args (help, eun etc...) docker run -d --name v2ray -v /path/to/config.json:/etc/v2fly/config.json -p 10086:10086 v2fly/v2fly-core run -c /etc/v2fly/config.json +``` +--- +# Gateway mode +You can use v2ray as a network gateway for serving a proxied network to another container or other devices in the network. + +For running the container in gateway mode you need to make some changes in you v2ray config file. + +1. Add an additional inbound with the dokodemo-door protocol for listening on the 12345 port (like example) +2. Add a mark of 255 to all the outbounds + +### Example of config file for gateway mode +```json +{ + "inbounds": [ + { + "port": 1080, + "protocol": "socks", + "sniffing": { + "enabled": true, + "destOverride": ["http", "tls"] + }, + "settings": { + "auth": "noauth" + } + }, + { + "tag":"transparent", + "port": 12345, + "protocol": "dokodemo-door", + "settings": { + "network": "tcp,udp", + "followRedirect": true + }, + "sniffing": { + "enabled": true, + "destOverride": [ + "http", + "tls" + ] + }, + "streamSettings": { // it's necessary + "sockopt": { + "tproxy": "tproxy", + "mark":255 + } + } + } + ], + "outbounds": [ + { + "tag": "proxy-1", + "protocol": "vmess", + "settings": { + "vnext": [ + ... + ] + }, + "streamSettings": { + "sockopt": { // You should add these settings for all of the outbounds + "mark": 255 + } + } + }, + { + "tag": "direct", + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIP" + }, + "streamSettings": { + "sockopt": { // Even for freedom + "mark": 255 + } + } + }, + { + "tag": "block", + "protocol": "blackhole", + "settings": { + "response": { + "type": "http" + } + } + }, + { + "tag": "dns-out", + "protocol": "dns", + "streamSettings": { + "sockopt": { + "mark": 255 + } + } + } + ], + "dns": { + "servers": [ + ... + ] + }, + "routing": { + "domainStrategy": "IPOnDemand", + "rules": [ + { + "type": "field", + "inboundTag": [ + "transparent" + ], + "port": 53, + "network": "udp", + "outboundTag": "dns-out" + }, + { // Directly connect to port 123 UDP traffic (NTP protocol) + "type": "field", + "inboundTag": [ + "transparent" + ], + "port": 123, + "network": "udp", + "outboundTag": "direct" + }, + ... + ] + } +} + +``` + +Please read [this topic](https://guide.v2fly.org/app/tproxy.html) for more details. + + +### Example of a home network gateway with docker compose +```yaml +version: '3.4' +services: + v2ray: + image: v2fly/v2fly-core + cap_add: + - NET_ADMIN # Required in gateway mode + volumes: + - ./testConfig.json:/etc/v2ray/config.json + environment: + - TPROXY=true # Active the gateway mode + command: ['run','-c','/etc/v2ray/config.json'] + networks: + vlan: + ipv4_address: 192.168.1.254 # The IP address of this container which other devices can use this IP as a gateway. + +networks: + vlan: + driver: macvlan + driver_opts: + parent: ens3 # The ethernet adaptor in the host system + ipam: + driver: default + config: + - subnet: 192.168.1.0/24 # Home network subnet + gateway: 192.168.1.1 # Home network gateway (your router ip) + +``` + + +### Example of a gateway for other containers with docker compose +```yaml +version: '3.4' +services: + v2ray: + image: v2fly/v2fly-core + cap_add: + - NET_ADMIN # Required in gateway mode + volumes: + - ./testConfig.json:/etc/v2ray/config.json + environment: + - TPROXY=true # Active the gateway mode + command: ['run','-c','/etc/v2ray/config.json'] + networks: + bridgenetwork: + ipv4_address: 192.168.30.1 + + test-conatiner: + image: weibeld/ubuntu-networking + depends_on: + - v2ray + stdin_open: true + privileged: true + networks: + bridgenetwork: + + command: > # Adding the v2ray container IP as a default gateway + sh -c "ip route del default && + ip route add default via 192.168.30.1 && + tail -f /dev/null" +networks: + bridgenetwork: + driver: bridge + ipam: + driver: default + config: + - subnet: "192.168.30.0/24" + gateway: "192.168.30.254" ``` \ No newline at end of file