erebe / wstunnel

Tunnel all your traffic over Websocket or HTTP2 - Bypass firewalls/DPI - Static binary available
BSD 3-Clause "New" or "Revised" License
4.15k stars 358 forks source link

wstunnel[4113]: Rejecting connection #343

Closed axrusar closed 3 weeks ago

axrusar commented 3 weeks ago

(ノಠ益ಠ)ノ彡┻━┻

Describe the goal

Establish a wireguard connection with wstunnel 5.0

Describe what does not work

wstunnel[4113]: Rejecting connection wstunnel[4113]: Rejecting connection

Describe your wstunnel setup

Server: ubuntu server 22.04.4 client: Linux mint 20.3, Linux mint 22

Followed this guide: https://nerdonthestreet.com/wiki?find=Set+Up+a+WireGuard+VPN+Server+with+WebSocket+Tunneling

I am using wstunnel 5.0 because that is what is used in the guide linked above. When i tried to use the latest wstunnel version 10, the service does not start on the server. I have actually setup wstunnel using version 5 (on the same client i am currently using to connect and same server) in the past without issues, so i have been pulling my hairs for the past few days and i can not pinpoint where the issue is. I am testing from the same system (Mint 21.3 client) i was able to connect before and and 2 fresh VMs (another mint 20.3 and a new 22).

When i start the connection on the client i get (all sensitive IPs are masked with xx below):

[#] source /etc/wireguard/wstunnel.sh && pre_up wg0
[#] Can't resolve 3.xx.xx.3
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 192.168.50.9/24 dev wg0
[#] ip link set mtu 65456 up dev wg0
[#] resolvconf -a wg0 -m 0 -x
[#] source /etc/wireguard/wstunnel.sh && post_up wg0

but running wg shows no traffic (transfer: 0 B received, 148 B sent)

If i run the wireguard connection to the server without the wstunnel, the connection works. And the server seems to be receiving the requests on port 443 based on what i posted in the title. When i start the connection, the same error loops indefinitely wstunnel[4113]: Rejecting connection

The wstunnel service on the server shows:

wstunnel.service - Tunnel WireGuard UDP over websocket
     Loaded: loaded (/etc/systemd/system/wstunnel.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2024-08-23 16:58:42 UTC; 27min ago
   Main PID: 4113 (wstunnel)
      Tasks: 6 (limit: 1120)
     Memory: 5.3M
        CPU: 781ms
     CGroup: /system.slice/wstunnel.service
             └─4113 /usr/local/bin/wstunnel -v --server wss://0.0.0.0:443 --restrictTo=127.0.0.1:51820

Aug 23 17:21:55 aws-ohio wstunnel[4113]: Rejecting connection
Aug 23 17:21:55 aws-ohio wstunnel[4113]: NEW incoming connection from xx.0.0.xx:1307 []
Aug 23 17:21:55 aws-ohio wstunnel[4113]: Rejecting connection
Aug 23 17:21:56 aws-ohio wstunnel[4113]: NEW incoming connection from xx.0.0.xx:1308 []
Aug 23 17:21:56 aws-ohio wstunnel[4113]: Rejecting connection
Aug 23 17:21:56 aws-ohio wstunnel[4113]: NEW incoming connection from xx.0.0.xx:1309 []
Aug 23 17:21:56 aws-ohio wstunnel[4113]: Rejecting connection
Aug 23 17:23:23 aws-ohio wstunnel[4113]: wstunnel: ConnectionClosed
Aug 23 17:23:48 aws-ohio wstunnel[4113]: NEW incoming connection from xx.0.0.xx:57588 []
Aug 23 17:23:48 aws-ohio wstunnel[4113]: Rejecting connection

Here is the modified script i am using on the client to bypass hostname resolution as i do not use a domain (pre_up section where remote_ip=${remote} is added):

#!/usr/bin/env bash

#
# Original script downloaded from: https://github.com/Kirill888/notes/blob/wg-tunnel-update/wireguard/scripts/wstunnel.sh
# Modified by jnsgruk to use `ip route` for modern Linux distros
#
DEFAULT_HOSTS_FILE='/etc/hosts'

read_host_entry () {
    local host=$1
    local hfile=${2:-${DEFAULT_HOSTS_FILE}}
    awk -v host="$host" '{
     if( !($0~"^[ ]*#") && $2==host )
       print $1, ($0~"## wstunnel end-point")?"auto":"manual"
     }' "${hfile}"
}

add_host_entry () {
    local host=$1
    local ip=$2
    local hfile=${3:-${DEFAULT_HOSTS_FILE}}
    echo -e "${ip}\t${host}\t## wstunnel end-point" >> "${hfile}"
}

update_host_entry () {
    local host=$1
    local ip=$2
    local hfile=${3:-${DEFAULT_HOSTS_FILE}}
    local edited
    edited=$(awk -v host="$host" -v ip="$ip" '{
      if( !($0~"^[ ]*#") && $2==host && ($0~"## wstunnel end-point") )
        print ip "\t" host "\t" "## wstunnel end-point"
      else
        print $0
      }' "${hfile}")

    echo "${edited}" > "${hfile}"
}

delete_host_entry () {
    local host=$1
    local hfile=${2:-${DEFAULT_HOSTS_FILE}}
    local edited
    edited=$(awk -v host="$host" '{
      if( !($0~"^[ ]*#") && $2==host && ($0~"## wstunnel end-point") )
        ;
      else
        print $0
      }' "${hfile}")

    echo "${edited}" > "${hfile}"
}

maybe_update_host () {
    local host="$1"
    local current_ip="$2"
    local hfile=${3:-${DEFAULT_HOSTS_FILE}}
    local recorded_ip h_mode

    read -r recorded_ip h_mode < <(read_host_entry "${host}" "${hfile}") || true

    if [[ -z "${recorded_ip}" ]]; then
        echo "[#] Add new entry ${host} => <${current_ip}>"
        add_host_entry "${host}" "${current_ip}" "${hfile}"
    else
        if [[ "${recorded_ip}" == "${current_ip}" ]]; then
            echo "[#] Recorded address is already correct"
        else
            if [[ "${h_mode}" == "auto" ]]; then
                echo "[#] Updating ${recorded_ip} -> ${current_ip}"
                update_host_entry "${host}" "${current_ip}" "${hfile}"
            else
                echo "[#] Manual entry doesn't match current ip: ${recorded_ip} -> ${current_ip}"
                exit 2
            fi
        fi
    fi
}

launch_wstunnel () {
    local host=${REMOTE_HOST}
    local rport=${REMOTE_PORT:-51820}
    local wssport=${WSS_PORT:-443}
    local lport=${LOCAL_PORT:-${rport}}
    local prefix=${WS_PREFIX:-"wstunnel"}
    local user=${1:-"nobody"}
    local cmd

    cmd=$(command -v wstunnel)
    cmd="sudo -n -u ${user} -- $cmd"

    export NO_COLOR=true
    nohup $cmd &>/dev/null \
      client \
      --http-upgrade-path-prefix "${prefix}" \
      -L "udp://127.0.0.1:${lport}:127.0.0.1:${rport}" \
      "wss://${host}:${wssport}" &
    echo "$!"
}

pre_up () {
    local wg=$1
    local cfg="/etc/wireguard/${wg}.wstunnel"
    local remote remote_ip gw wstunnel_pid hosts_file _dnsmasq

    if [[ -f "${cfg}" ]]; then
        # shellcheck disable=SC1090
        source "${cfg}"
        remote=${REMOTE_HOST}
        #remote_ip=${REMOTE_IP:-$(dig +short "${remote}" | head -n 1)}
        hosts_file=${UPDATE_HOSTS}
        _dnsmasq=${USING_DNSMASQ:-0}
    else
        echo "[#] Missing config file: ${cfg}"
        exit 1
    fi

    if [[ -z "${remote_ip}" ]]; then
        echo "[#] Can't resolve ${remote}"
        #remote_ip=${remote}
        remote_ip=${remote}
    fi

    if [[ -f "${hosts_file}" ]]; then
        # Cache DNS in
        maybe_update_host "${remote}" "${remote_ip}" "${hosts_file}"

        [[ $_dnsmasq -eq 0 ]] || killall -HUP dnsmasq || true
    fi

    # Find out current route to ${remote_ip} and make it explicit
    gw=$(ip route get "${remote_ip}" | cut -d" " -f3)
    ip route add "${remote_ip}" via "${gw}" > /dev/null 2>&1 || true
    # Start wstunnel in the background
    wstunnel_pid=$(launch_wstunnel nobody)

    # save state
    mkdir -p /var/run/wireguard
    echo "${wstunnel_pid} ${remote} ${remote_ip} \"${hosts_file}\" ${_dnsmasq}" > "/var/run/wireguard/${wg}.wstunnel"
}

post_up () {
    local tun=$1
    ip route add 0.0.0.0/1 dev "${tun}" > /dev/null 2>&1
    ip route add ::0/1 dev "${tun}" > /dev/null 2>&1
    ip route add 128.0.0.0/1 dev "${tun}" > /dev/null 2>&1
    ip route add 8000::/1 dev "${tun}" > /dev/null 2>&1
}

post_down () {
    local tun=$1
    local state_file="/var/run/wireguard/${tun}.wstunnel"
    local wstunnel_pid remote remote_ip hosts_file _dnsmasq

    if [[ -f "${state_file}" ]]; then
        read -r wstunnel_pid remote remote_ip hosts_file _dnsmasq < "${state_file}"
        # unquote
        hosts_file=${hosts_file%\"}
        hosts_file=${hosts_file#\"}

        rm "${state_file}"
    else
        echo "[#] Missing state file: ${state_file}"
        exit 1
    fi

    kill -TERM "${wstunnel_pid}" > /dev/null 2>&1 || true

    if [[ -n "${remote_ip}" ]]; then
        ip route delete "${remote_ip}" > /dev/null 2>&1 || true
    fi

    if [[ -f "${hosts_file}" ]]; then
        delete_host_entry "${remote}" "${hosts_file}"
        [[ $_dnsmasq -eq 0 ]] || killall -HUP dnsmasq || true
    fi
}

My ISP started blocking wireguard, the wireguard connections i mentioned working are the same i was using a week ago (same keys as before) so i need wstunnel to work. Thank you for any tips.

erebe commented 3 weeks ago

Please upgrade to the latest version of wstunnel. See the FAQ section for using wireguard with wstunnel https://github.com/erebe/wstunnel?tab=readme-ov-file#wireguard

axrusar commented 3 weeks ago

Ok i downloaded version 10 and trying the basics as per the instructions on that link. Here i start wstunnel on the server:

root@aws-ohio:~# wstunnel server --restrict-to localhost:51001 wss://[::]:4433
2024-08-28T15:02:28.262471Z  INFO wstunnel::embedded_certificate: Generating self-signed tls certificate    
2024-08-28T15:02:28.263152Z  INFO wstunnel: Starting wstunnel server v10.1.0 with config WsServerConfig { socket_so_mark: None, bind: [::]:4433, websocket_ping_frequency: Some(30s), timeout_connect: 10s, websocket_mask_frame: false, restriction_config: None, tls: true, mTLS: false }
2024-08-28T15:02:28.263284Z  INFO wstunnel::tunnel::server::server: Starting wstunnel server listening on [::]:4433

Port 4433 is open on the server. I also added the route using the local WAN ip of the server and the router gateway. Note i use port 51001 for the wireguard connections.

This is the client trying to connect:

root@mint22VM:/etc/wstunnel# wstunnel client -L 'udp://51001:localhost:51001?timeout_sec=0' wss://3.xx.xx.3:4433
024-08-28T15:08:39.506147Z  INFO wstunnel::protocols::udp::server: New UDP connection from 127.0.0.1:34041
2024-08-28T15:08:39.506772Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to 3.xx.xx.3:4433    
2024-08-28T15:08:43.933434Z  WARN wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint 3.xx.xx.3:4433 due to timeout of 10s elapsed    
2024-08-28T15:08:49.509066Z  WARN wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint 3.xx.xx.3:4433 due to timeout of 10s elapsed    
2024-08-28T15:08:49.910477Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to 3.xx.xx.3:4433    
2024-08-28T15:08:59.912138Z  WARN wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint 3.xx.xx.3:4433 due to timeout of 10s elapsed    
2024-08-28T15:09:00.713694Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to 3.xx.xx.3:4433    

Times out and keeps looping every 10 seconds.

I do not see any instructions on how to actually install wstunnel.. i just extracted it from the wstunnel_10.1.0_linux_amd64.tar.gz file and gave it +x permissions.

erebe commented 3 weeks ago

That's ok for the installation, only extracting and chmod +x is enough.

From the log it seems tve port 4433 is filtered/blocked between your client and server.

Check with another well known port, that is not filtered. i.e: 443, 995, 53, 8080,...

axrusar commented 3 weeks ago

The ports are not filtered/blocked on the server. I have control of the firewall. To make it clear i ran another test on port 443 that i am currently using for v2ray and it is working.

While v2ray is active on the server on port 443, from the connecting client i run:

nc -zv 3.xx.xx.3 443
Connection to 3.xx.xx.3 443 port [tcp/https] succeeded!

Now confirmed there is no issues with port 443, I stop the v2ray service on the server to make the port available for wstunnel. So if i try again:

nc -zv 3.xx.xx.3 443
nc: connect to 3.xx.xx.3 port 443 (tcp) failed: Connection refused

This confirms port 443 is free and no services are using it now.

Then i run wstunnel on the server using port 443:

root@aws-ohio:~# wstunnel server --restrict-to localhost:51001 wss://127.0.0.1:443
2024-08-29T09:21:33.761772Z  INFO wstunnel::embedded_certificate: Generating self-signed tls certificate    
2024-08-29T09:21:33.762411Z  INFO wstunnel: Starting wstunnel server v10.1.0 with config WsServerConfig { socket_so_mark: None, bind: 127.0.0.1:443, websocket_ping_frequency: Some(30s), timeout_connect: 10s, websocket_mask_frame: false, restriction_config: None, tls: true, mTLS: false }
2024-08-29T09:21:33.762556Z  INFO wstunnel::tunnel::server::server: Starting wstunnel server listening on 127.0.0.1:443

and run nc again from the client:

nc -zv 3.xx.xx.3 443
nc: connect to 3.xx.xx.3 port 443 (tcp) failed: Connection refused

Same timeout in the client if i try to connect:

root@mint22VM:/etc/wstunnel# wstunnel client -L 'udp://51001:localhost:51001?timeout_sec=0' wss://3.xx.xx.3:443
024-08-29T09:32:56.155218Z  WARN wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint 3.xx.xx.3:443 due to timeout of 10s elapsed    
2024-08-29T09:33:47.355691Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to 3.xx.xx.3:443    
2024-08-29T09:33:57.357163Z  WARN wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint 3.xx.xx.3:443 due to timeout of 10s elapsed    
2024-08-29T09:35:39.758288Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to 3.xx.xx.3:443    
2024-08-29T09:35:45.325769Z ERROR tunnel{id="01919d79-1acd-7313-8305-afe60be5cb3b" remote="localhost:51001"}: wstunnel::tunnel::client::client: failed to get a connection to the server from the pool: TimedOut

although if i run netstat on the server while wstunnel is running it shows the port is in use:

root@aws-ohio:~# netstat -tuln | grep 443
tcp        0      0 127.0.0.1:443         0.0.0.0:*               LISTEN     

Server system information"

System:
  Kernel: 6.5.0-1023-aws x86_64 bits: 64 Console: pty pts/0
    Distro: Ubuntu 22.04.4 LTS (Jammy Jellyfish)

wstunnel v10.1.0

As mentioned earlier, i have control of the firewall and using any other port (4433, 44333) does not make a difference. I do have multiple other ports open on it and they all work. The server itself has the firewall disabled, the ports are opened from the inbound rules in the AWS security panel. The server does not have any special routing rules configuration that may be interfering, it is pretty much a vanilla Ubuntu server to run only wireguard and now v2ray while trying to setup wstunnel.

Thank you!!

erebe commented 3 weeks ago

in your last example, the server is listening only on the loopback interface (127.0.0.1)

root@aws-ohio:~# wstunnel server --restrict-to localhost:51001 wss://127.0.0.1:443

try with wss://[::]:443 or wss://0.0.0.0:443

axrusar commented 3 weeks ago

Ok it looks like there is a connection now running:

root@aws-ohio:~# wstunnel server --restrict-to localhost:51001 wss://[::]:443

In the client i see the ping pong loop:

wstunnel client -L 'udp://51001:localhost:51001?timeout_sec=0' wss://3.xx.xx.3:443
2024-08-29T13:18:13.992370Z  INFO tunnel{id="01919e42-7b2b-7ff3-b0fe-af5e07f5d913" remote="localhost:51001"}: wstunnel::tunnel::transport::websocket: received frame Ping    
2024-08-29T13:18:14.134617Z  INFO tunnel{id="01919e42-7b2b-7ff3-b0fe-af5e07f5d913" remote="localhost:51001"}: wstunnel::tunnel::transport::websocket: received frame Pong    
2024-08-29T13:18:43.993501Z  INFO tunnel{id="01919e42-7b2b-7ff3-b0fe-af5e07f5d913" remote="localhost:51001"}: wstunnel::tunnel::transport::websocket: received frame Ping    
2024-08-29T13:18:44.134992Z  INFO tunnel{id="01919e42-7b2b-7ff3-b0fe-af5e07f5d913" remote="localhost:51001"}: wstunnel::tunnel::transport::websocket: received frame Pong 

But then i start the wireguard connection and i lose internet connection. There is no reply from the server and the client shows:

2024-08-29T13:10:42.731137Z  INFO wstunnel::protocols::udp::server: New UDP connection from 127.0.0.1:34479
2024-08-29T13:10:42.731287Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to 3.xx.xx.3:443    
2024-08-29T13:10:52.499749Z  INFO tunnel{id="01919e3b-be69-7713-8ab2-c41e1fefdcf1" remote="localhost:51001"}: wstunnel::tunnel::transport::websocket: received frame Ping    
2024-08-29T13:10:52.733195Z  WARN wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint 3.xx.xx.3:443 due to timeout of 10s elapsed    

I am using the same wireguard configuration that was working before the ISP started blocking the protocol. In the client looks like this:

[Interface]
PrivateKey = eDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2o= 
Address = 192.168.69.9/32
#MTU = 1400
DNS = 1.1.1.1

[Peer]
PublicKey = osxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn0=
Endpoint = localhost:51001
AllowedIPs = 0.0.0.0/0

So i only changed the endpoint to localhost. running wg on the server shows the wireguard server is active listening.

Server config:

[Interface]
PrivateKey=gBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxm3I=

Address=192.168.69.1/24
ListenPort=51001
PostUp=iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown=iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
## Home
PublicKey=SatxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEk=
AllowedIPs=192.168.69.9
erebe commented 3 weeks ago

you need to set a static route now to your server to avoid the loop https://github.com/erebe/wstunnel?tab=readme-ov-file#wireguard-and-wstunnel-

or in your client allowed ip exclude your server from it, instead of 0.0.0.0/0 check https://github.com/erebe/wstunnel/issues/252#issuecomment-2030281446

axrusar commented 3 weeks ago

Thank you erebe for your patience and kindness. I got it going now, problem was i added the route to the server instead of the client. Good luck and thank you for your time.