tun2proxy / tun2proxy

Tunnel (TUN) interface for SOCKS and HTTP proxies
MIT License
518 stars 95 forks source link

About IPv6 #18

Closed ssrlive closed 1 year ago

ssrlive commented 1 year ago

This is the issue that I meeting.

My VPS don't support IPv6, so it's always failed.

image

so I think that whether we set a switch in VirtualDNS to enable/disable IPv6 query?

In actually, it's fine while I access github, and it's bad when youtube, google, twitter.

This is a success request. image

blechschmidt commented 1 year ago

Virtual DNS is not used at all in your case. It appears that you are running into the issue which I have outlined in c8e1872efe325b76447c9f393eb8f3a4e451be74. As the DNS resolution of your machine appears to bypass the tunnel, the virtual DNS feature will not see your DNS traffic.

As a quick fix, I would suggest to modify /etc/resolv.conf using sudo sh -c "echo nameserver 198.18.0.1 > /etc/resolv.conf". Then, DNS traffic should be routed through the tunnel.

In the long term, it would probably be a good idea to add an option like --setup auto to tun2proxy, which performs all the steps outlined in the setup instructions and updates the /etc/resolv.conf accordingly. This would require starting tun2proxy as root, but privileges could be dropped after the setup.

ssrlive commented 1 year ago

how about we traffic all UDP package include DNS to remote server? overtls can traffic UDP package.

ssrlive commented 1 year ago

you are right. after quick fix the browser works fine.

As a quick fix, I would suggest to modify /etc/resolv.conf using sudo sh -c "echo nameserver 198.18.0.1 > /etc/resolv.conf".

blechschmidt commented 1 year ago

While UDP support is on the todo list, that will not fix this particular problem. DNS resolution on Linux machines works roughly as follows:

  1. Programs (including libraries like the libc) will parse /etc/resolv.conf and extract the DNS nameservers.
  2. Netlink (the underlying protocol that is also used by the ip tools belonging to iproute2) will be used to determine whether there is an IPv6 default route. If so, the machine does not only perform DNS A requests for IPv4 addresses, but also DNS AAAA requests for IPv6 addresses.

Virtual DNS intercepts the DNS queries generated by the machine. This requires that the queries are actually sent through the tunnel interface (e.g. tun0). In your scenario, this is not the case. Likely, your original /etc/resolv.conf contains a nameserver entry with some local IP address. If you have a look at your IP routes using ip route, the nameserver IP is likely inside some of the IP ranges listed there (excluding the 0.0.0.0/1 and 128.0.0.0/1 ones configured for tun2proxy) that are routed through your ethernet interface. Often, this is some /24 range. Routing works by considering the smallest ranges first. If a packet is sent to 1.2.3.4 and there are overlapping routes like 1.2.3.0/24 and 0.0.0.0/1, it will take the 1.2.3.0/24 route. Therefore, simply adding UDP support would still bypass the tunnel. Even if you always routed traffic to the IP addresses inside /etc/resolv.conf through the tunnel, you would run into problems because if you have a local DNS server configured, DNS queries routed through the tunnel will be made to that particular local IP address which the proxy server has no access to.

As a result, there is only one real solution to this problem: Update the /etc/resolv.conf to only use a nameserver IP address that is routed through the tunnel. I.e. if virtual DNS is used, you can use the quick fix. If virtual DNS is not used, UDP support (will not work for SOCKS4 or HTTP) or some UDP to TCP proxy solution in conjunction with a third-party DNS server, such as 1.1.1.1, is required.

blechschmidt commented 1 year ago

The --setup auto feature now handles all the setup stuff described in the README. Everything is restored to the original state when Ctrl+C is pressed or when the program terminates through an error.

ssrlive commented 1 year ago

Cool

ssrlive commented 1 year ago

a script

#! /usr/bin/bash

# Please set the following parameters according to your environment
BYPASS_IP=123.45.67.89
PROXY_IP=127.0.0.1
PROXY_PORT=1080
PROXY_TYPE=SOCKS5

function _main() {
    local is_envonly="${1}"

    sudo ip tuntap add name tun0 mode tun
    sudo ip link set tun0 up

    sudo ip route add "$BYPASS_IP" $(ip route | grep '^default' | cut -d ' ' -f 2-)

    sudo ip route add 128.0.0.0/1 dev tun0
    sudo ip route add 0.0.0.0/1 dev tun0

    sudo ip route add ::/1 dev tun0
    sudo ip route add 8000::/1 dev tun0

    sudo sh -c "echo nameserver 198.18.0.1 > /etc/resolv.conf"

    if [ "$is_envonly" = true ]; then
        read -n 1 -s -r -p "Don't do anything. If you want to exit and clearup environment, press any key..."
        echo ""
        restore
    else
        trap 'echo "" && echo "tun2proxy exited with code: $?" && restore' EXIT
        ./target/debug/tun2proxy --tun tun0 --proxy "$PROXY_TYPE://$PROXY_IP:$PROXY_PORT"
    fi
}

function restore() {
    sudo ip link del tun0
    sudo systemctl restart systemd-resolved.service
}

function main() {
    local action=${1}
    [ -z ${1} ] && action="envonly"
    case "${action}" in
        envonly)
            _main true
            ;;
        runtun2proxy)
            _main false
            ;;
        *)
            echo "Arguments error! [${action}]"
            echo "Usage: `basename $0` [envonly|runtun2proxy]"
            ;;
    esac

    exit 0
}

main "$@"
blechschmidt commented 1 year ago

Not sure if you still need the script. When using the setup function, privileges are now dropped to the nobody user: https://github.com/blechschmidt/tun2proxy/blob/c0cff1da580097b0ae1d6b1b1d72f765af7da634/src/setup.rs#L300-L307

A separate process will keep running as root to be able to tear down the tunnel interface but it does nothing apart from waiting for a termination signal, while the network components are isolated: https://github.com/blechschmidt/tun2proxy/blob/6d9767db422d422522f0986e6cb4c7667bc60d93/src/setup.rs#L280-L292

So it should be reasonably safe.

ssrlive commented 1 year ago

I'm sorry. I run the script with sudo , so the tun0 is root privilage. I have find it.