Giter Club home page Giter Club logo

wiretap's Introduction

Wiretap

Wiretap is a transparent, VPN-like proxy server that tunnels traffic via WireGuard and requires no special privileges to run.

In this diagram, the client has generated and installed WireGuard configuration files that will route traffic destined for 10.0.0.0/24 through a WireGuard interface. Wiretap is then deployed to the server with a configuration that connects to the client as a WireGuard peer. The client can then interact with resources local to the server as if on the same network and chain additional servers to reach new networks. Access to the Wiretap network can also be shared with other clients.

Wiretap Diagram

Quick Start

  1. Download binaries from the releases page, one for your client machine and one for your server (if different os/arch)
  2. Run ./wiretap configure --port <port> --endpoint <socket> --routes <routes> with the appropriate arguments
  3. Import the resulting wiretap.conf and wiretap_relay.conf files into WireGuard on the client machine
  4. Copy and paste the server command output that best suits your target system into Wiretap on the server machine
  5. Add more servers and clients as needed with the add subcommand

Requirements

Client Systems

Server Systems

  • Bidirectional UDP access to client on one port. By default the server initiates the handshake to the client because it is more likely to have outbound UDP than inbound, but the reverse is easily configurable

While not ideal, Wiretap can still work with TCP instead of UDP. See the experimental TCP Tunneling section for a step-by-step guide.

Installation

Grab a binary from the releases page. You may want two binaries if the OS/ARCH are different on the client and server machines.

If you want to compile it yourself or can't find the OS/ARCH you're looking for, install Go (>=1.20) from https://go.dev/dl/ and use the provided Makefile.

Usage

Configure

Wiretap Configure Arguments

On the client machine, run Wiretap in configure mode to build a config

./wiretap configure --port <port> --endpoint <socket> --routes <routes>
  • --port sets the listening port of the Client's Relay interface. It's set to 51820 by default. Note that the E2EE listening port does not need to be accessible to the Server
  • --endpoint tells the Server how to connect to the Client's Relay interface (the E2EE interfaces already know how to talk to each other if the Relay interfaces are working)
  • --routes is the equivalent of WireGuard's AllowedIPs setting. This tells the Client to route traffic that matches these IP ranges through Wiretap

Following the example in the diagram:

./wiretap configure --port 1337 --endpoint 1.3.3.7:1337 --routes 10.0.0.0/24
Configurations successfully generated.
Import the two configs into WireGuard locally and pass the arguments below to Wiretap on the remote machine.

config: wiretap_relay.conf
────────────────────────────────
[Interface]
PrivateKey = cGsJkcVIajZW7kfN5SMwijmMx59ke7FZ+qdZOcsNDE0=
Address = 172.16.0.1/32
Address = fd:16::1/128
ListenPort = 1337

[Peer]
PublicKey = kMj7HwfYYFO/XEHNFK2kz9cBd7vTHk63fhygyuYLMzI=
AllowedIPs = 172.17.0.0/24,fd:17::/48
────────────────────────────────

config: wiretap.conf
────────────────────────────────
[Interface]
PrivateKey = YCTRVwB4xOEcBtifVmhjMhRYL7+DOlDP5VdHZGclZGg=
Address = 172.19.0.1/32
Address = fd:19::1/128
ListenPort = 51821
MTU = 1340

[Peer]
PublicKey = 3ipWthpJzqVo5wcb1TSDS1M8YOiBQYBPmbj3mVD/5Fg=
AllowedIPs = 10.0.0.0/24,::2/128
Endpoint = 172.17.0.2:51821
────────────────────────────────

server config: wiretap_server.conf

server command:
POSIX Shell:  WIRETAP_RELAY_INTERFACE_PRIVATEKEY=WDH8F6rSUZDyQFfEsRjWLCnapU254qrSAfpGyGs+N1Y= WIRETAP_RELAY_PEER_PUBLICKEY=Ta75SvIb2v2V8EDo6oE2Fvsys/CNlkzW+aPjxdY+Dlc= WIRETAP_RELAY_PEER_ENDPOINT=1.3.3.7:1337 WIRETAP_E2EE_INTERFACE_PRIVATEKEY=GKzGBe3qS7JuLp0vMAErBW6lAewvmFowCIbcgwzComg= WIRETAP_E2EE_PEER_PUBLICKEY=cXddDGWCzd5igux4FDv97XBsyLH0SRPehhTz3E2IXBM= WIRETAP_E2EE_PEER_ENDPOINT=172.16.0.1:51821 ./wiretap serve
 PowerShell:  $env:WIRETAP_RELAY_INTERFACE_PRIVATEKEY="WDH8F6rSUZDyQFfEsRjWLCnapU254qrSAfpGyGs+N1Y="; $env:WIRETAP_RELAY_PEER_PUBLICKEY="Ta75SvIb2v2V8EDo6oE2Fvsys/CNlkzW+aPjxdY+Dlc="; $env:WIRETAP_RELAY_PEER_ENDPOINT="1.3.3.7:1337"; $env:WIRETAP_E2EE_INTERFACE_PRIVATEKEY="GKzGBe3qS7JuLp0vMAErBW6lAewvmFowCIbcgwzComg="; $env:WIRETAP_E2EE_PEER_PUBLICKEY="cXddDGWCzd5igux4FDv97XBsyLH0SRPehhTz3E2IXBM="; $env:WIRETAP_E2EE_PEER_ENDPOINT="172.16.0.1:51821"; .\wiretap.exe serve
Config File:  ./wiretap serve -f wiretap_server.conf

Note Wiretap uses 2 WireGuard interfaces per node in order to safely and scalably chain together servers. This means your client will bind to more than one port, but only the Relay Interface port needs to be accessible by the Server. See the How It Works section for details. Use --simple if your setup requires a single interface on the client

Install the resulting config either by copying and pasting the output or by importing the new wiretap.conf and wiretap_relay.conf files into WireGuard:

  • If using a GUI, select the menu option similar to Import Tunnel(s) From File
  • If you have wg-quick installed, sudo wg-quick up ./wiretap.conf and sudo wg-quick up ./wiretap_relay.conf

Don't forget to disable or remove the tunnels when you're done (e.g., sudo wg-quick down ./wiretap.conf and sudo wg-quick down ./wiretap_relay.conf)

Deploy

On the remote machine, upload the binary and then copy the command with the private and public keys to start Wiretap in server mode:

$env:WIRETAP_RELAY_INTERFACE_PRIVATEKEY="WDH8F6rSUZDyQFfEsRjWLCnapU254qrSAfpGyGs+N1Y="; $env:WIRETAP_RELAY_PEER_PUBLICKEY="Ta75SvIb2v2V8EDo6oE2Fvsys/CNlkzW+aPjxdY+Dlc="; $env:WIRETAP_RELAY_PEER_ENDPOINT="1.3.3.7:1337"; $env:WIRETAP_E2EE_INTERFACE_PRIVATEKEY="GKzGBe3qS7JuLp0vMAErBW6lAewvmFowCIbcgwzComg="; $env:WIRETAP_E2EE_PEER_PUBLICKEY="cXddDGWCzd5igux4FDv97XBsyLH0SRPehhTz3E2IXBM="; $env:WIRETAP_E2EE_PEER_ENDPOINT="172.16.0.1:51821"; .\wiretap.exe serve

There are two other ways to pass arguments to the server:

  1. With a config file: -f wiretap_server.conf
  2. The legacy method of passing command line arguments (--endpoint 1.3.3.7:1337 ...). Be aware that this method exposes arguments to other users on the system. A compromised private key can be used to connect to the client as a peer and/or decrypt traffic

Confirm that the relay interfaces on the client and server have successfully completed a handshake. The client should see successful handshakes in whatever WireGuard interface is running. If using the command-line tools, check with wg show. By default the E2EE handshake will not occur until the client sends data.

Now the client should be able to interact with the routes specified in the configure command!

Add Server (Optional)

Wiretap Add Server Arguments

The add server subcommand is meant to extend the Wiretap network to reach new areas of a target network. One client and at least one server must be configured and deployed before adding another server. Servers can attach to any other server or the client itself.

Note All servers must be deployed before adding additional clients

You can view the state of the network and see API addresses with ./wiretap status

./wiretap status
╭────────────────────────╮
│ Wiretap Network Status │
╰────────────┬───────────╯
             │
  ╭──────────┴──────────╮
  │client               │
  │                     │
  │  relay: Ta75SvIb... │
  │   e2ee: cXddDGWC... │
  │                     │
  ╰──────────┬──────────╯
             │
  ╭──────────┴──────────╮
  │server               │
  │  relay: kMj7HwfY... │
  │   e2ee: 3ipWthpJ... │
  │                     │
  │    api: ::2         │
  │ routes: 10.0.0.0/24 │
  ╰─────────────────────╯

If you plan to attach a server directly to the client, the status command just confirms that everything is working as expected and the network layout is correct. If you want to attach a server to another server you must specify the API address in your add server command. In the example, we will want to attach to the server with API address ::2. This command will generate a configuration you can deploy to the new server (through environment variables or a config), just like with the configure command:

./wiretap add server --server-address ::2 --endpoint 10.0.0.2:51820 --routes 10.0.1.0/24
Configurations successfully generated.
Import the updated config(s) into WireGuard locally and pass the arguments below to Wiretap on the new remote server.

config: wiretap.conf
────────────────────────────────
[Interface]
PrivateKey = YCTRVwB4xOEcBtifVmhjMhRYL7+DOlDP5VdHZGclZGg=
Address = 172.19.0.1/32
Address = fd:19::1/128
ListenPort = 51821
MTU = 1340

[Peer]
PublicKey = 3ipWthpJzqVo5wcb1TSDS1M8YOiBQYBPmbj3mVD/5Fg=
AllowedIPs = 10.0.0.0/24,::2/128
Endpoint = 172.17.0.2:51821

[Peer]
PublicKey = YOVI9nOvjOWTre0OVzrjx8qsYRgyuSLWndv28S2udiQ=
AllowedIPs = 10.0.1.0/24,::3/128
Endpoint = 172.17.0.3:51821
────────────────────────────────

server config: wiretap_server_1.conf

POSIX Shell:  WIRETAP_RELAY_INTERFACE_PRIVATEKEY=sLERnxT2+VdwwcJOTUHK5fa5sIN7oJ1Jww9n42txrEQ= WIRETAP_RELAY_INTERFACE_IPV4=172.17.0.3 WIRETAP_RELAY_INTERFACE_IPV6=fd:17::3 WIRETAP_RELAY_PEER_PUBLICKEY=kMj7HwfYYFO/XEHNFK2kz9cBd7vTHk63fhygyuYLMzI= WIRETAP_RELAY_PEER_ALLOWED=172.16.0.0/16,fd:16::/40 WIRETAP_RELAY_PEER_ENDPOINT=10.0.0.2:51820 WIRETAP_E2EE_INTERFACE_PRIVATEKEY=uF79x5X8q3Vd/ajWMR5XyDt/haahtpy5PkJj9b+OaUE= WIRETAP_E2EE_INTERFACE_API=::3 WIRETAP_E2EE_PEER_PUBLICKEY=cXddDGWCzd5igux4FDv97XBsyLH0SRPehhTz3E2IXBM= WIRETAP_E2EE_PEER_ENDPOINT=172.16.0.1:51821 ./wiretap serve
 PowerShell:  $env:WIRETAP_RELAY_INTERFACE_PRIVATEKEY="sLERnxT2+VdwwcJOTUHK5fa5sIN7oJ1Jww9n42txrEQ="; $env:WIRETAP_RELAY_INTERFACE_IPV4="172.17.0.3"; $env:WIRETAP_RELAY_INTERFACE_IPV6="fd:17::3"; $env:WIRETAP_RELAY_PEER_PUBLICKEY="kMj7HwfYYFO/XEHNFK2kz9cBd7vTHk63fhygyuYLMzI="; $env:WIRETAP_RELAY_PEER_ALLOWED="172.16.0.0/16,fd:16::/40"; $env:WIRETAP_RELAY_PEER_ENDPOINT="10.0.0.2:51820"; $env:WIRETAP_E2EE_INTERFACE_PRIVATEKEY="uF79x5X8q3Vd/ajWMR5XyDt/haahtpy5PkJj9b+OaUE="; $env:WIRETAP_E2EE_INTERFACE_API="::3"; $env:WIRETAP_E2EE_PEER_PUBLICKEY="cXddDGWCzd5igux4FDv97XBsyLH0SRPehhTz3E2IXBM="; $env:WIRETAP_E2EE_PEER_ENDPOINT="172.16.0.1:51821"; .\wiretap.exe serve
Config File:  ./wiretap serve -f wiretap_server_1.conf

The client's E2EE configuration will be modified, so you need to reimport it. For example, wg-quick down ./wiretap.conf and wg-quick up ./wiretap.conf. If you are attaching a server directly to the client, the Relay interface will also need to be refreshed.

Now you can use any of the server command options to deploy Wiretap to the new server. It will then connect to the already existing server.

At this point the new routes should be usable! You can confirm that everything looks correct with wiretap status:

./wiretap status
╭────────────────────────╮
│ Wiretap Network Status │
╰────────────┬───────────╯
             │
  ╭──────────┴──────────╮
  │client               │
  │                     │
  │  relay: Ta75SvIb... │
  │   e2ee: cXddDGWC... │
  │                     │
  ╰──────────┬──────────╯
             │
  ╭──────────┴──────────╮
  │server               │
  │  relay: kMj7HwfY... │
  │   e2ee: 3ipWthpJ... │
  │                     │
  │    api: ::2         │
  │ routes: 10.0.0.0/24 │
  ╰──────────┬──────────╯
             │
  ╭──────────┴──────────╮
  │server               │
  │  relay: GMkUzfDy... │
  │   e2ee: YOVI9nOv... │
  │                     │
  │    api: ::3         │
  │ routes: 10.0.1.0/24 │
  ╰─────────────────────╯

Now the client can reach 10.0.0.0/24 and 10.0.1.0/24. From here you can attach more servers to any of the three nodes.

Add Client (Optional)

Wiretap Add Client Arguments

The add client subcommand can be used to share access to the Wiretap network with others.

Note All servers must be deployed before adding additional clients

Adding a client is very similar to the other commands. It will generate a wiretap.conf and wiretap_relay.conf for sharing. Make sure that all of the first-hop servers (any server directly attached to the original client) can reach or be reached by the new client. Once you get the endpoint information from whoever will be running the new client run:

./wiretap add client --port 1337 --endpoint 1.3.3.8:1337
Configurations successfully generated.
Have a friend import these files into WireGuard

config: wiretap_relay_1.conf
────────────────────────────────
[Interface]
PrivateKey = UEgzp6zv8lNnpih31RfzKsz+BLyN5qNfh6PbCdF1Cmg=
Address = 172.16.0.2/32
Address = fd:16::2/128
ListenPort = 1337

[Peer]
PublicKey = kMj7HwfYYFO/XEHNFK2kz9cBd7vTHk63fhygyuYLMzI=
AllowedIPs = 172.17.0.0/24,fd:17::/48
────────────────────────────────

config: wiretap_1.conf
────────────────────────────────
[Interface]
PrivateKey = 8AhL1kDjwBn/IoY4KLd5mMP4GQsyMYNsqYm3aM/bHnE=
Address = 172.19.0.2/32
Address = fd:19::2/128
ListenPort = 51821
MTU = 1340

[Peer]
PublicKey = 3ipWthpJzqVo5wcb1TSDS1M8YOiBQYBPmbj3mVD/5Fg=
AllowedIPs = 10.0.0.0/24,::2/128
Endpoint = 172.17.0.2:51821

[Peer]
PublicKey = YOVI9nOvjOWTre0OVzrjx8qsYRgyuSLWndv28S2udiQ=
AllowedIPs = 10.0.1.0/24,::3/128
Endpoint = 172.17.0.3:51821
────────────────────────────────

Send these files and have the recipient import them into WireGuard to have access to everything in the Wiretap network! By default the routes (AllowedIPs) are copied over, but can be modified by the recipient as needed.

Port Forwarding

Warning Port forwarding exposes services on your local machine to the remote network, use with caution

You can expose a service on the client by using the expose subcommand. For example, to allow remote systems to access port 80/tcp on your local machine, you could run:

./wiretap expose --local 80 --remote 8080

Now all Wiretap servers will be bound to port 8080/tcp and proxy connections to your services on port 80/tcp. By default this uses IPv6, so make sure any listening services support IPv6 as well. To configure Wiretap to only use IPv4, use the configure subcommand's --disable-ipv6 option.

To dynamically forward all ports using SOCKS5:

./wiretap expose --dynamic --remote 8080

All servers will spin up a SOCKS5 server on port 8080 and proxy traffic to your local machine and can be used like this:

curl -x socks5://<server-ip>:8080 http://<any-ip>:1337

The destination IP will be rewritten by the server so you can put any address.

List

Use ./wiretap expose list to see all forwarding rules currently configured.

Remove

Use ./wiretap remove with the same arguments used in expose to delete a rule. For example, to remove the SOCKS5 example above:

./wiretap expose remove --dynamic --remote 8080

How It Works

A traditional VPN can't be installed by unprivileged users because VPNs rely on dangerous operations like changing network routes and working with raw packets.

Wiretap bypasses this requirement by rerouting traffic to a user-space TCP/IP network stack, where a listener accepts connections on behalf of the true destination. Then it creates a new connection to the true destination and copies data between the endpoint and the peer. This is similar to how https://github.com/sshuttle/sshuttle and https://github.com/nicocha30/ligolo-ng work, but relies on WireGuard as the tunneling mechanism rather than SSH or TLS.

To build secure and scalable tunnels across multiple hops, each node in the Wiretap network has two interfaces: Relay and E2EE (end-to-end encrypted). The Relay nodes simply relay packets between nodes, but cannot see the plaintext. When a Relay node sees a packet that does not match routing rules, it forwards it to its own E2EE interface where contents can be decrypted by only that interface. There are two layers of WireGuard encapsulation between any two nodes.

Wiretap E2EE Architecture

Help

./wiretap --help --show-hidden
Usage:
  wiretap [flags]
  wiretap [command]

Available Commands:
  add         Add peer to wiretap
  configure   Build wireguard config
  expose      Expose local services to servers
  help        Help about any command
  ping        Ping wiretap server API
  serve       Listen and proxy traffic into target network
  status      Show peer layout

Flags:
  -h, --help          help for wiretap
      --show-hidden   show hidden flag options
  -v, --version       version for wiretap

Use "wiretap [command] --help" for more information about a command.

Features

  • Network
    • IPv4
    • IPv6
    • ICMPv4: Echo requests and replies
    • ICMPv6: Echo requests and replies
  • Transport
    • TCP
      • Transparent connections
      • RST response when port is unreachable
      • Reverse Port Forward
      • Reverse Socks5 Support
    • UDP
      • Transparent "connections"
      • ICMP Destination Unreachable when port is unreachable
      • Reverse Port Forward
  • Application
    • API internal to Wiretap for dynamic configuration
    • Chain servers together to tunnel traffic through an arbitrary number of machines
    • Add clients after deployment for multi-user support

Demo

The demo has four hosts and three networks for testing multi-hop/nested tunnels, but only the first target host is reached in the examples below.

┌──────────┐
│ client   │
│          │
│ 10.1.0.2 │
│ fd:1::2  ├┬───────────────────────┐
├──────────┼│ exposed network       │
├──────────┼│ 10.1.0.0/16,fd:1::/64 │
│ 10.1.0.3 ├┴───────────────────────┘
│ fd:1::3  │
│          │
│ server   │
│          │
│ 10.2.0.3 │
│ fd:2::3  ├┬───────────────────────┐
├──────────┼│ target network        │
├──────────┼│ 10.2.0.0/16,fd:2::/64 │
│ 10.2.0.4 ├┴───────────────────────┘
│ fd:2::4  │
│          │
│ target   │
│          │
│ 10.3.0.4 │
│ fd:3::4  ├┬───────────────────────┐
├──────────┼│ target2 network       │
├──────────┼│ 10.3.0.0/16,fd:3::/64 │
│ 10.3.0.5 ├┴───────────────────────┘
│ fd:3::5  │
│          │
│ target2  │
└──────────┘

Video

wiretap_demo.mp4

Step-By-Step

You have unprivileged access to the server host and want to reach the target host from the client host using Wiretap.

Setup

Clone this repo.

Start the demo containers with:

docker compose up --build

Open new tabs for interactive sessions with the client and server machines:

docker exec -it wiretap-client-1 bash
docker exec -it wiretap-server-1 bash

Observe Network Limitations

The target network, and therefore the target host, is unreachable from the client machine. Both the server and target hosts are running a web service on port 80, so try interacting with each of the services from each of the hosts:

Accessing the server's web service from the client should work:

client$ curl http://10.1.0.3

Accessing the target web service from the client should not work, but doing the same thing from the server machine will:

# fails
client$ curl http://10.2.0.4
server$ curl http://10.2.0.4

Configure

Configure Wiretap from the client machine. Remember, --endpoint is how the server machine should reach the client and --routes determines which traffic is routed through Wiretap.

  • --endpoint needs to be the client address and the default WireGuard port: 10.1.0.2:51820
  • --routes needs to be the subnet of the target network: 10.2.0.0/16. But there is also an IPv6 subnet, so we should also put fd:2::/64. If you just wanted to route traffic to the target host, you could put 10.2.0.4/32 here instead
./wiretap configure --endpoint 10.1.0.2:51820 --routes 10.2.0.0/16,fd:2::/64

Install the newly created WireGuard configs with:

wg-quick up ./wiretap_relay.conf
wg-quick up ./wiretap.conf

Copy and paste the Wiretap arguments printed by the configure command into the server machine prompt. It should look like this:

WIRETAP_RELAY_INTERFACE_PRIVATEKEY=<key> WIRETAP_RELAY_PEER_PUBLICKEY=<key> WIRETAP_RELAY_PEER_ENDPOINT=10.1.0.2:51820 WIRETAP_E2EE_INTERFACE_PRIVATEKEY=<key> WIRETAP_E2EE_PEER_PUBLICKEY=<key> WIRETAP_E2EE_PEER_ENDPOINT=172.16.0.1:51821 ./wiretap serve

Test

The WireGuard handshake should be complete. Confirm with:

wg show

If the handshake was successful the client should be able to reach the target network transparently. Confirm by running the same test that failed before:

client$ curl http://10.2.0.4

That's it! Try scanning, pinging, and anything else you can think of (please submit an issue if you think something should work but doesn't!). Here are a few ideas:

  • HTTP
    • curl http://10.2.0.4
    • curl http://[fd:2::4]
  • Nmap
    • nmap 10.2.0.4 -v
    • nmap -6 fd:2::4 -v
  • ICMP
    • ping 10.2.0.4
    • ping fd:2::4
  • UDP
    • nmap -sU 10.2.0.4 -v
    • nmap -sU -6 fd:2::4 -v

Exercise

Try to reach the second target by adding another server! You should be able to successfully run curl http://10.3.0.5 from the client host if performed correctly. The status command should output something similar to:

╭────────────────────────╮
│ Wiretap Network Status │
╰────────────┬───────────╯
             │
  ╭──────────┴──────────╮
  │client               │
  │                     │
  │  relay: Ta75SvIb... │
  │   e2ee: cXddDGWC... │
  │                     │
  ╰──────────┬──────────╯
             │
  ╭──────────┴──────────╮
  │server               │
  │  relay: kMj7HwfY... │
  │   e2ee: 3ipWthpJ... │
  │                     │
  │    api: ::2         │
  │ routes: 10.2.0.0/16 │
  ╰──────────┬──────────╯
             │
  ╭──────────┴──────────╮
  │server               │
  │  relay: GMkUzfDy... │
  │   e2ee: YOVI9nOv... │
  │                     │
  │    api: ::3         │
  │ routes: 10.3.0.0/16 │
  ╰─────────────────────╯

Teardown

To bring down the WireGuard interfaces on the client machine, run:

wg-quick down ./wiretap_relay.conf
wg-quick down ./wiretap.conf

Experimental

TCP Tunneling

Note Performance will suffer, only use TCP Tunneling as a last resort

If you have no outbound or inbound UDP access, you can still use Wiretap, but you'll need to tunnel WireGuard traffic through TCP. This should only be used as a last resort. From WireGuard's Known Limitations page:

TCP Mode

WireGuard explicitly does not support tunneling over TCP, due to the classically terrible network performance of tunneling TCP-over-TCP. Rather, transforming WireGuard's UDP packets into TCP is the job of an upper layer of obfuscation (see previous point), and can be accomplished by projects like udptunnel and udp2raw.

Another great tool that has similar cross-platform capabilities to Wiretap is Chisel. We can use chisel to forward a UDP port to the remote system over TCP. To use:

Run chisel server on the client system, specifying a TCP port you can reach from the server system:

./chisel server --port 8080

On the server system, forward the port with this command using the same TCP port you specified in the previous command and using the ListenPort you specified when configuring Wiretap (the default is 51820). The format is <localport>:0.0.0.0:<remoteport>/udp.

In this example, we're forwarding 51821/udp on the server to 51820 on the client:

./chisel client <endpoint address>:8080 51821:0.0.0.0:51820/udp

Finally, run Wiretap with the forwarded local port as your endpoint on the server system:

WIRETAP_RELAY_INTERFACE_PRIVATEKEY=<key> WIRETAP_RELAY_PEER_PUBLICKEY=<key> WIRETAP_E2EE_INTERFACE_PRIVATEKEY=<key> WIRETAP_E2EE_PEER_PUBLICKEY=<key> WIRETAP_E2EE_PEER_ENDPOINT=172.16.0.1:51821 ./wiretap serve --endpoint localhost:51821

Add Clients To Any Server

Note Clients added to arbitrary servers do not currently have the same capabilities as clients added to first-hop servers (the default)

Clients can be attached to any server in the network by using the --server-address <api-address> argument when running wiretap add client. This allows a client on a different network than the first client to still gain access to all of the Wiretap network's routes. But this has some limitations.

In this example, a new client is added to the second server in the right branch of a Wiretap network. This client will only be able to access routes via the right branch of the network and not the left branch because the branches are only joined through an existing client, which does not route traffic from other clients:

        ┌─────┐
        │  C  │
        └┬───┬┘
         │   │
    ┌────┴┐ ┌┴────┐
    │  S  │ │  S  │
    └──┬──┘ └──┬──┘
       │       │
    ┌──┴──┐ ┌──┴──┐
    │  S  │ │  S  ◄───────┐
    └─────┘ └─────┘       │
                       ┌──┴─┐
                       │ C  │
                       └────┘

You may also need to manually edit the resulting wiretap.conf for the new client to remove any AllowedIPs entries that already exist in the new client's host routing table. If the server that the client is attaching to has a route for 10.2.0.0/16, but the Client already has that route (because that's where it lives), then remove the 10.2.0.0/16 entry from the wiretap.conf file before importing into WireGuard. Leave the API address and any other routes you wish to access.

wiretap's People

Contributors

dennydai avatar dependabot[bot] avatar luker983 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wiretap's Issues

WTF? Routes have a default but is required

Error: required flag(s) "routes" not set
Usage:
  wiretap configure [flags]

Flags:
  -r, --routes strings             CIDR IP ranges that will be routed through wiretap (default [0.0.0.0/32])
  -e, --endpoint string            socket address of wireguard listener that server will connect to (example "1.2.3.4:51820")
      --outbound                   client will initiate handshake to server, set endpoint to server address
  -p, --port int                   port of local wireguard relay listener (default 51820)
      --relay-output string        wireguard relay config output filename (default "wiretap_relay.conf")
      --e2ee-output string         wireguard E2EE config output filename (default "wiretap.conf")
  -s, --server-output string       wiretap server config output filename (default "wiretap_server.conf")
  -c, --clipboard                  copy configuration args to clipboard
      --simple                     disable multihop and multiclient features for a simpler setup
  -0, --api string                 address of server API service (default "::2/128")
      --ipv4-relay string          ipv4 relay address (default "172.16.0.1/32")
      --ipv6-relay string          ipv6 relay address (default "fd:16::1/128")
      --ipv4-e2ee string           ipv4 e2ee address (default "172.19.0.1/32")
      --ipv6-e2ee string           ipv6 e2ee address (default "fd:19::1/128")
      --ipv4-relay-server string   ipv4 relay address of server (default "172.17.0.2/32")
      --ipv6-relay-server string   ipv6 relay address of server (default "fd:17::2/128")
  -k, --keepalive int              tunnel keepalive in seconds, only applies to outbound handshakes (default 25)
  -m, --mtu int                    tunnel MTU (default 1420)
      --disable-ipv6               disables IPv6
  -h, --help                       help for configure

Global Flags:
      --show-hidden   show hidden flag options

required flag(s) "routes" not set

Flag --routes have a default [0.0.0.0/32] but it is required, how to use default then?

Not closing connection on RST

I'm sorry for not investigation this further and please accept the 'observation' rather than a bug report.

I'm using https://thc.org/segfault/wireguard with the wiretap v0.3.0 (--simple branch) with WIRETAP_SIMPLE=true ./wiretap_linux_amd64 serve --ipv4-relay 192.168.0.1 --ipv6-relay fd::1 --allowed 192.168.0.1/28,fd::1/125

The Exit Node is a Linux x86_64 running wiretap.
The origin host runs nmap -n -Pn -sT -p1-512 --open scanme.nmap.org

Issue: The scan never finishes.

It appears that the wiretap keeps the connection open even when the Origin-Server sent a RST.

On the Exit node:

root@gs6:~# tcpdump -n -i ens3 host 45.33.32.156 and port 80
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
16:42:56.401101 IP 51.83.131.42.55984 > 45.33.32.156.80: Flags [S], seq 2942595855, win 1460, options [mss 1460,sackOK,TS val 766681198 ecr 0,nop,wscale 2], length 0
16:42:56.579900 IP 45.33.32.156.80 > 51.83.131.42.55984: Flags [S.], seq 1777498995, ack 2942595856, win 65160, options [mss 1460,sackOK,TS val 2105695364 ecr 766681198,nop,wscale 7], length 0
16:42:56.579928 IP 51.83.131.42.55984 > 45.33.32.156.80: Flags [.], ack 1, win 365, options [nop,nop,TS val 766681377 ecr 2105695364], length 0

On the origin (where nmap is running)

┌──(EXIT:Dirt)(root💀sf-BiologyMetal)-[~]
└─# tcpdump -n  -i wgExit port 80
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wgExit, link-type RAW (Raw IP), snapshot length 262144 bytes


16:42:56.389574 IP 192.168.0.2.40372 > 45.33.32.156.80: Flags [S], seq 1050340797, win 64860, options [mss 1380,sackOK,TS val 2860797468 ecr 0,nop,wscale 7], length 0
16:42:56.591281 IP 45.33.32.156.80 > 192.168.0.2.40372: Flags [S.], seq 4170675645, ack 1050340798, win 27584, options [mss 1380,sackOK,TS val 3287297152 ecr 2860797468,nop,wscale 5], length 0
16:42:56.591319 IP 192.168.0.2.40372 > 45.33.32.156.80: Flags [.], ack 1, win 507, options [nop,nop,TS val 2860797670 ecr 3287297152], length 0
16:42:56.591406 IP 192.168.0.2.40372 > 45.33.32.156.80: Flags [R.], seq 1, ack 1, win 507, options [nop,nop,TS val 2860797670 ecr 3287297152], length 0

On the Exit Node the connection still shows ESTAB:

root@gs6:~# ss -antp | grep -F 45.33.32.156
ESTAB  0      0       51.83.131.42:55984   45.33.32.156:80    users:(("wiretap_linux_a",pid=125573,fd=11))

My gut feeling is that wiretap only processes for a 'clean close' (FIN) but ignores the RST.

High Memory usage per TCP connection

Wiretap seems to use around 14MBytes of memory (rss) for each new tcp connection. That's without kernel memory and without TCP buffers (which reside inside the kernel; not userland).

The problem is that this causes wiretap to fail (and exit; or killed by the OOM).

The problem can be re-created when establishing 88k TCP connections when wiretap is running on a Linux system with 2GBytes of RAM (sending 88k TCP SYN).

Killed process 125774 (wiretap_linux_a) total-vm:2368460kB, anon-rss:1198968kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:3356kB oom_score_adj:0

It seems odd that the userland wiretap allocates 14MBytes of memory before the TCP connection has exchanged any data.

The desirable solution would be any of these two:

  1. Reduce the memory requirement on wiretap. Not much memory needs to be allocated until the SYN-ACK is received (e.g. wiretap's connect(2) completes).
  2. When memory allocation fails then make wiretap fail the connection (send RST/FIN upstream) instead of dying. RST/FIN either for the failed connection or start freeing connections that are outstanding (not completed) - starting with the oldest - top make memory available for the most recent connection.

Feature request: Retrieve stats from WT-EXIT

A REST-API call from the origin host to the WT-EXIT to retrieve information/stats about the WT-EXIT.

curl http://172.16.0.1/info

Info/Stats may include

  1. Configured IP ranges of all interfaces on the WT-EXIT
  2. Uptime / Load / Users

Multiple clients in "outbound" mode

Here is my setup:

  • A client: a mobile phone fully under NAT
  • A server: a container, under NAT as well, but with several ports exposed to the internet.

I was able to create a tunnel between them using the following commands:

# Generate server and client config
./wiretap configure --routes 0.0.0.0/0 --outbound --endpoint SERVER_IP:SERVER_PORT --simple

# Run server inside container
./wiretap serve -f wiretap_server.conf --simple --port SERVER_PORT

It works fine, but now I'm not sure how to add more clients to the same server: the config seems to accept only a single peer. Is it possible to have more clients in such setup? If not, is it possible to be implemented?

Error after a successful DNS query terminates server process

I'm getting an error after DNS requests that causes the server process to panic and terminate. My current workaround is to wrap the server in a while loop, but that's not very elegant.

Roughly the same stack trace when the server is on linux or windows:
wiretap[.exe] : panic: unknown network protocol number 0
wiretap/transport/udp.getDataFromPacket()
wiretap/transport/udp/udp.go:128

Using the client as a "proxy" server

So, how can I use the client as a "proxy" server to run tools locally according to this scheme: NAT Machine > Wiretap Client on VPS > Wiretap Server?

Set Rlimit_NOFILE

default soft limit for ulimit -n is 1024. Would be nice if wiretap sets this to the max allowed. Otherwise connections start dropping if more than 1k are open.

current work around is ulimit -n $(ulimit -Hn) before starting wiretap.

docker test setup / Invalid MAC of handshake

I was trying out the docker test setup but can't make it work. The handshake fails due to invalid MAC. Also it seems no wireguard interfaces get created on server side - I'm unsure if that is expected, but probably not.
EDIT: no, this is expected bc it shall run unprivileged and thus doesn't use real interfaces.

wiretap version: 67e3e20
kernel version: 6.0.6

host:

$ sudo docker compose up --build
# enable wireguard logging
$ echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control

client:

root@5b7aba15837f:/wiretap# ./wiretap configure -e 10.1.0.2:51821 -r 10.2.0.0/16,fd:2::/64

Configurations successfully generated.
Import the config(s) into WireGuard locally and pass the arguments below to Wiretap on the remote machine.

config: wiretap_relay.conf
────────────────────────────────
[Interface]
PrivateKey = QDDwmCLVFlLRI6maCkhuch37rM7pf5iMjDYYDj/+40k=
Address = 172.16.0.1/32
Address = fd:16::1/128
ListenPort = 51820

[Peer]
PublicKey = 8AIvsGagQCUWENFNVefPbi8bmzGDkLz5ukTZmrl3S2Q=
AllowedIPs = 172.17.0.0/24,fd:17::/48
────────────────────────────────

config: wiretap.conf
────────────────────────────────
[Interface]
PrivateKey = KNLkwlr9SqbDEfyJetZ5zEeNoi6y54hvjYujGSxy81Y=
Address = 172.19.0.1/32
Address = fd:19::1/128
ListenPort = 51821
MTU = 1340

[Peer]
PublicKey = 03kzMw5XaIZstJIAwFuRtmukqraa2eNAUOWpKWv1mTA=
AllowedIPs = 10.2.0.0/16,fd:2::/64,::2/128
Endpoint = 172.17.0.2:51821
────────────────────────────────

server config: wiretap_server.conf

server command:
POSIX Shell:  WIRETAP_RELAY_INTERFACE_PRIVATEKEY=sM4xXCWOttLPsTFmEtCwkUCQFH0B0MSd0CaitMGGWG4= WIRETAP_RELAY_PEER_PUBLICKEY=WgWBQT1h/drdEzspcbkAVdK+zw/ff553Z7lBwkYa/gg= WIRETAP_RELAY_PEER_ENDPOINT=10.1.0.2:51821 WIRETAP_E2EE_INTERFACE_PRIVATEKEY=SF6F0rHVA+WvgD0/q21/2M5R4aY6Plvf63IWyssYp2s= WIRETAP_E2EE_PEER_PUBLICKEY=kF+PrySBovhd2eChKWCCjkrqID4cvrBkX0k0PBZ7ExE= WIRETAP_E2EE_PEER_ENDPOINT=172.16.0.1:51821 ./wiretap serve
 PowerShell:  $env:WIRETAP_RELAY_INTERFACE_PRIVATEKEY="sM4xXCWOttLPsTFmEtCwkUCQFH0B0MSd0CaitMGGWG4="; $env:WIRETAP_RELAY_PEER_PUBLICKEY="WgWBQT1h/drdEzspcbkAVdK+zw/ff553Z7lBwkYa/gg="; $env:WIRETAP_RELAY_PEER_ENDPOINT="10.1.0.2:51821"; $env:WIRETAP_E2EE_INTERFACE_PRIVATEKEY="SF6F0rHVA+WvgD0/q21/2M5R4aY6Plvf63IWyssYp2s="; $env:WIRETAP_E2EE_PEER_PUBLICKEY="kF+PrySBovhd2eChKWCCjkrqID4cvrBkX0k0PBZ7ExE="; $env:WIRETAP_E2EE_PEER_ENDPOINT="172.16.0.1:51821"; .\wiretap.exe serve
Config File:  ./wiretap serve -f wiretap_server.conf

root@5b7aba15837f:/wiretap# wg-quick up ./wiretap.conf ; wg-quick up ./wiretap_relay.conf
[#] ip link add wiretap type wireguard
[#] wg setconf wiretap /dev/fd/63
[#] ip -4 address add 172.19.0.1/32 dev wiretap
[#] ip -6 address add fd:19::1/128 dev wiretap
[#] ip link set mtu 1340 up dev wiretap
[#] ip -6 route add ::2/128 dev wiretap
[#] ip -6 route add fd:2::/64 dev wiretap
[#] ip -4 route add 10.2.0.0/16 dev wiretap
[#] ip link add wiretap_relay type wireguard
[#] wg setconf wiretap_relay /dev/fd/63
[#] ip -4 address add 172.16.0.1/32 dev wiretap_relay
[#] ip -6 address add fd:16::1/128 dev wiretap_relay
[#] ip link set mtu 1420 up dev wiretap_relay
[#] ip -6 route add fd:17::/48 dev wiretap_relay
[#] ip -4 route add 172.17.0.0/24 dev wiretap_relay

server:

root@f42df23e78e8:/wiretap# WIRETAP_RELAY_INTERFACE_PRIVATEKEY=sM4xXCWOttLPsTFmEtCwkUCQFH0B0MSd0CaitMGGWG4= WIRETAP_RELAY_PEER_PUBLICKEY=WgWBQT1h/drdEzspcbkAVdK+zw/ff553Z7lBwkYa/gg= WIRETAP_RELAY_PEER_ENDPOINT=10.1.0.2:51821 WIRETAP_E2EE_INTERFACE_PRIVATEKEY=SF6F0rHVA+WvgD0/q21/2M5R4aY6Plvf63IWyssYp2s= WIRETAP_E2EE_PEER_PUBLICKEY=kF+PrySBovhd2eChKWCCjkrqID4cvrBkX0k0PBZ7ExE= WIRETAP_E2EE_PEER_ENDPOINT=172.16.0.1:51821 ./wiretap serve -d

Relay configuration:
────────────────────────────────
[Peer]
PublicKey = 8AIvsGagQCUWENFNVefPbi8bmzGDkLz5ukTZmrl3S2Q=
AllowedIPs = 0.0.0.0/32
────────────────────────────────

E2EE configuration:
────────────────────────────────
[Peer]
PublicKey = 03kzMw5XaIZstJIAwFuRtmukqraa2eNAUOWpKWv1mTA=
AllowedIPs = 0.0.0.0/32
────────────────────────────────

private_key=b0ce315c258eb6d2cfb1316612d0b0914090147d01d0c49dd026a2b4c186586e
listen_port=51820
public_key=5a0581413d61fddadd133b2971b90055d2becf0fdf7f9e7767b941c2461afe08
endpoint=10.1.0.2:51821
allowed_ip=172.16.0.1/32
allowed_ip=fd:16::1/128
persistent_keepalive_interval=25

DEBUG: 2023/09/22 11:48:59 UAPI: Updating private key
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 2 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 1 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 2 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 3 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 4 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 3 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 4 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 2 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 5 - started
DEBUG: 2023/09/22 11:48:59 UAPI: Updating listen port
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 6 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 6 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 8 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 8 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 1 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 7 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 4 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 5 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 5 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 6 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 3 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 7 - started
DEBUG: 2023/09/22 11:48:59 Routine: event worker - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 1 - started
DEBUG: 2023/09/22 11:48:59 Interface up requested
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - UAPI: Created
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - UAPI: Updating endpoint
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 7 - started
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - UAPI: Adding allowedip
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - UAPI: Adding allowedip
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - UAPI: Updating persistent keepalive interval
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - Starting
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 8 - started
DEBUG: 2023/09/22 11:48:59 Routine: TUN reader - started
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - Routine: sequential sender - started
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - Sending keepalive packet
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - Sending handshake initiation
DEBUG: 2023/09/22 11:48:59 Routine: receive incoming v6 - started
DEBUG: 2023/09/22 11:48:59 UDP bind has been updated
DEBUG: 2023/09/22 11:48:59 peer(WgWB…a/gg) - Routine: sequential receiver - started
DEBUG: 2023/09/22 11:48:59 Routine: receive incoming v4 - started
DEBUG: 2023/09/22 11:48:59 Interface state was Down, requested Up, now Up
private_key=485e85d2b1d503e5af803d3fab6d7fd8ce51e1a63a3e5bdfeb7216cacb18a76b
listen_port=51821
public_key=905f8faf2481a2f85dd9e0a12960828e4aea203e1cbeb0645f49343c167b1311
endpoint=172.16.0.1:51821
allowed_ip=172.19.0.1/32
allowed_ip=fd:19::1/128
persistent_keepalive_interval=25

DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 4 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 8 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 6 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 7 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 2 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 4 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 2 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 7 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 5 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 1 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 5 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 1 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 7 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 1 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 6 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 2 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 3 - started
DEBUG: 2023/09/22 11:48:59 UAPI: Updating private key
DEBUG: 2023/09/22 11:48:59 UAPI: Updating listen port
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - UAPI: Created
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - UAPI: Updating endpoint
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - UAPI: Adding allowedip
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 5 - started
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - UAPI: Adding allowedip
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - UAPI: Updating persistent keepalive interval
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 8 - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 8 - started
DEBUG: 2023/09/22 11:48:59 Routine: handshake worker 3 - started
DEBUG: 2023/09/22 11:48:59 Routine: TUN reader - started
DEBUG: 2023/09/22 11:48:59 UDP bind has been updated
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - Starting
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - Sending keepalive packet
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 6 - started
DEBUG: 2023/09/22 11:48:59 Routine: encryption worker 4 - started
DEBUG: 2023/09/22 11:48:59 Routine: event worker - started
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - Routine: sequential receiver - started
DEBUG: 2023/09/22 11:48:59 Interface up requested
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - Sending handshake initiation
DEBUG: 2023/09/22 11:48:59 Routine: receive incoming makeReceive - started
DEBUG: 2023/09/22 11:48:59 peer(kF+P…7ExE) - Routine: sequential sender - started
DEBUG: 2023/09/22 11:48:59 Routine: decryption worker 3 - started
DEBUG: 2023/09/22 11:48:59 Routine: receive incoming makeReceive - started
DEBUG: 2023/09/22 11:48:59 Interface state was Down, requested Up, now Up
WIRETAP: 2023/09/22 11:48:59 API: API listener up
DEBUG: 2023/09/22 11:49:04 peer(kF+P…7ExE) - Handshake did not complete after 5 seconds, retrying (try 2)
DEBUG: 2023/09/22 11:49:04 peer(kF+P…7ExE) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:04 peer(WgWB…a/gg) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:09 peer(kF+P…7ExE) - Handshake did not complete after 5 seconds, retrying (try 3)
DEBUG: 2023/09/22 11:49:09 peer(kF+P…7ExE) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:09 peer(WgWB…a/gg) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:15 peer(WgWB…a/gg) - Handshake did not complete after 5 seconds, retrying (try 2)
DEBUG: 2023/09/22 11:49:15 peer(WgWB…a/gg) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:15 peer(kF+P…7ExE) - Handshake did not complete after 5 seconds, retrying (try 4)
DEBUG: 2023/09/22 11:49:15 peer(kF+P…7ExE) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:20 peer(kF+P…7ExE) - Handshake did not complete after 5 seconds, retrying (try 5)
DEBUG: 2023/09/22 11:49:20 peer(kF+P…7ExE) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:20 peer(WgWB…a/gg) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:25 peer(kF+P…7ExE) - Handshake did not complete after 5 seconds, retrying (try 6)
DEBUG: 2023/09/22 11:49:25 peer(kF+P…7ExE) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:25 peer(WgWB…a/gg) - Sending handshake initiation
DEBUG: 2023/09/22 11:49:30 peer(WgWB…a/gg) - Handshake did not complete after 5 seconds, retrying (try 2)
DEBUG: 2023/09/22 11:49:30 peer(WgWB…a/gg) - Sending handshake initiation

server in another shell:

root@6b6968ea03fe:/wiretap# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
213: eth0@if214: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:0a:01:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
217: eth1@if218: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:0a:02:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
root@6b6968ea03fe:/wiretap# wg

client:

root@5b7aba15837f:/wiretap# ./wiretap status
2023/09/22 12:03:04 failed to fetch node's configuration as peer: Get "http://::2:80/serverinfo?": dial tcp [::2]:80: i/o timeout
root@5b7aba15837f:/wiretap# wg show
interface: wiretap
  public key: kF+PrySBovhd2eChKWCCjkrqID4cvrBkX0k0PBZ7ExE=
  private key: (hidden)
  listening port: 51821

peer: 03kzMw5XaIZstJIAwFuRtmukqraa2eNAUOWpKWv1mTA=
  endpoint: 172.17.0.2:51821
  allowed ips: 10.2.0.0/16, fd:2::/64, ::2/128
  transfer: 0 B received, 3.18 KiB sent

interface: wiretap_relay
  public key: WgWBQT1h/drdEzspcbkAVdK+zw/ff553Z7lBwkYa/gg=
  private key: (hidden)
  listening port: 51820

peer: 8AIvsGagQCUWENFNVefPbi8bmzGDkLz5ukTZmrl3S2Q=
  allowed ips: 172.17.0.0/24, fd:17::/48

host:

sudo dmesg | grep wireguard
[4389322.734042] wireguard: wiretap: Invalid MAC of handshake, dropping packet from 10.1.0.3:51820
[4389327.760379] wireguard: wiretap: Invalid MAC of handshake, dropping packet from 10.1.0.3:51820
[4389332.914449] wireguard: wiretap: Invalid MAC of handshake, dropping packet from 10.1.0.3:51820

WT & masscan. Only the first open port is reported

This problem does never show up if I'm using WG on both sides. It shows up when I'm using WT on the EXIT-NODE
The bug is re-produceable (i tested 20x the same scenario and it showed up reliably).

I'm testing the current github from branch tcp-fix. I'm scanning for 2 ports on a single target only. Both ports are open on the target. Only the first one is found.

On the origin server (running wireguard)

masscan --interface wgExit --rate 1 -p31337,22 --open-only 45.33.32.156

Packets on origin server (wireguard):

13:09:42.916290 IP 172.16.0.2.49782 > 45.33.32.156.31337: Flags [S], seq 699471134, win 1024, length 0
13:09:43.073437 IP 45.33.32.156.31337 > 172.16.0.2.49782: Flags [S.], seq 3059500064, ack 699471135, win 27584, options [mss 1380], length 0
13:09:43.073500 IP 172.16.0.2.49782 > 45.33.32.156.31337: Flags [R], seq 699471135, win 0, length 0
13:09:43.916450 IP 172.16.0.2.49782 > 45.33.32.156.31337: Flags [R], seq 699471135, win 1200, length 0

13:09:44.916482 IP 172.16.0.2.49782 > 45.33.32.156.22: Flags [S], seq 2369022976, win 1024, length 0

Observe that the TCP SYN-ACK from port 22 is never send to the origin server. We only the the outgoing SYN.

Packet on Exit-Node to target (running wiretap):

15:09:42.918608 IP 192.145.44.201.49070 > 45.33.32.156.31337: Flags [S], seq 299369726, win 16060, length 0
15:09:43.070073 IP 45.33.32.156.31337 > 192.145.44.201.49070: Flags [S.], seq 619693497, ack 299369727, win 65160,  length 0
15:09:43.070131 IP 192.145.44.201.49070 > 45.33.32.156.31337: Flags [.], ack 1, win 8, length 0
15:09:43.222053 IP 45.33.32.156.31337 > 192.145.44.201.49070: Flags [F.], seq 1, ack 1, win 510, options [nop,nop,TS val 2032056807 ecr 1905127897], length 0
15:09:43.224657 IP 192.145.44.201.49070 > 45.33.32.156.31337: Flags [.], ack 2, win 8, length 0

15:09:44.918731 IP 192.145.44.201.36134 > 45.33.32.156.22: Flags [S], seq 292390217, win 16060, length 0
15:09:45.070204 IP 45.33.32.156.22 > 192.145.44.201.36134: Flags [S.], seq 3384812886, ack 292390218, win 65160, length 0
15:09:45.070277 IP 192.145.44.201.36134 > 45.33.32.156.22: Flags [.], ack 1, win 8, length 0
15:09:45.227020 IP 45.33.32.156.22 > 192.145.44.201.36134: Flags [P.], seq 1:45, ack 1, win 510, length 44: SSH: SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.13
15:09:45.227053 IP 192.145.44.201.36134 > 45.33.32.156.22: Flags [.], ack 45, win 8, length 0

15:09:48.071226 IP 192.145.44.201.49070 > 45.33.32.156.31337: Flags [F.], seq 1, ack 2, win 8, length 0
15:09:48.223085 IP 45.33.32.156.31337 > 192.145.44.201.49070: Flags [.], ack 2, win 510, length 0
15:09:50.070754 IP 192.145.44.201.36134 > 45.33.32.156.22: Flags [R.], seq 1, ack 45, win 8, length 0

The socket information on the exit node shows that the data is in the recv-q (44 bytes, "OpenSSH_..."):

tcp       44      0 192.145.44.201:36134    45.33.32.156:22        

The data stays in the RECV-Q for 5 seconds before the socket is closed.

The expected behaviour is for WT to:

  1. Send SYN/ACK to origin-host when TCP to target completes
  2. Send data received from target to origin-host

My gut feeling is that WT misses that the TCP connection has been established successfully and then kills it after 5 seconds.

It is odd because it works when I'm using nmap instead of masscan:

 nmap -p31337,22 -Pn -sS 45.33.32.156

The only difference that I can see is that nmap uses the Linux kernel (rather than raw TCP) and thus the SYN is re-send 2 times:

# FIRST SYN to port 22
13:16:49.292759 IP 172.16.0.2.42152 > 45.33.32.156.22: Flags [S], seq 2471212292, win 1024, options [mss 1460], length 0

13:16:49.292816 IP 172.16.0.2.42152 > 45.33.32.156.31337: Flags [S], seq 2471212292, win 1024, options [mss 1460], length 0
13:16:49.451170 IP 45.33.32.156.31337 > 172.16.0.2.42152: Flags [S.], seq 2053963635, ack 2471212293, win 27584, options [mss 1380], length 0
13:16:49.451203 IP 172.16.0.2.42152 > 45.33.32.156.31337: Flags [R], seq 2471212293, win 0, length 0

# SECOND SYN to port 22. Why is this needed? 
13:16:51.092230 IP 172.16.0.2.42154 > 45.33.32.156.22: Flags [S], seq 2471081222, win 1024, options [mss 1460], length 0

13:16:51.250134 IP 45.33.32.156.22 > 172.16.0.2.42154: Flags [S.], seq 2537989258, ack 2471081223, win 27584, options [mss 1380], length 0
13:16:51.250179 IP 172.16.0.2.42154 > 45.33.32.156.22: Flags [R], seq 2471081223, win 0, length 0

My gut says that WT somehow needs this 2nd SYN?

UPnP

Hello, I'm using this on a Windows server, I connect my XBOX to it via router with wireguard, i have a problem that some applications and voice chat don't work on xbox, i noticed in the router logs that xbox opens UPnP port, when I use xray-core with a simple client server wireguard configuration everything works, BUT in the case of xray-core xbox doesn't open the UPnP port

About Nested Tunnels

Regarding Nested Tunnels, I still don't quite understand how to add configuration and Endpoint settings to the client's conf file. Can you explain in detail?
My operation is to generate a config that does not contain Endpoint, and then specify the --endpoint on hop2 as the ip of hop1
Then I don't know how to operate

Standalone mode?

Hello,

Does wiretap works as a https or socks proxy, without executing any commands on wireguard server?

So it would be a standalone mode that expose a port for proxy passing through wireguard server.

SYN-SENT userland timeout

I'm using https://thc.org/segfault/wireguard with the wiretap v0.3.0 (--simple branch) with WIRETAP_SIMPLE=true ./wiretap_linux_amd64 serve --ipv4-relay 192.168.0.1 --ipv6-relay fd::1 --allowed 192.168.0.1/28,fd::1/125

The Exit Node is a Linux x86_64 running wiretap.
The origin host runs network scans using nmap or masscan.

The userland wiretap process tcp connect keeps the connection for a very long time in state SYN-SENT.
This can cause port exhaustion on the exit node (wiretap) when scanning a non-existing host on the Internet:

┌──(EXIT:Dirt)(root💀sf-BiologyMetal)-[~]
└─# nmap -n -Pn -sS -p- --open 30.31.32.33

and even worse if masscan is used:

┌──(EXIT:Dirt)(root💀sf-BiologyMetal)-[~]
└─# masscan --interface wgExit -p- --range 30.31.32.0/24  --source-ip 192.168.0.3 --banners --rate 1000

It would be desirable for wiretap to close the connection between wiretap and the target (and not forward a RST/FIN to upstream) after 10 seconds. The assumption is that if the target hasn't responded with a SYN-ACK within 10 seconds then the wiretap can 'drop' the connection.

The origin-server may still re-transmit the SYN again and again (in case it's not a masscan/nmap-scan) but in that case and with the original 'forwarding connection' having been closed already, wiretap would detect the re-transmitted SYN as a first SYN from Origin-server and just call Connect() to the target again.....

Feature Request: Reverse Port Forwarding

A method to tunnel back ports from the WT-EXIT back to the origin host (via REST api?).

To open a port forward from the WT-EXIT make a call from the origin-host to the WT-EXIT list so:

curl -s http://172.16.0.1/fwd -dport=31337

Thus would forward any new TCP connection to the EXIT-IP of WT-EXIT back to 172.16.0.1 (the origin host). Other options:

-dproto=<udp/tcp>          -- to select protocol. Default is TCP.
-daction=<del/delall/list> -- Delete one specific or all port forwards or list all forwards
-ddst=<IP:port>            -- Destination ip/port (default to 172.16.0.2:port)

(could also allow -dport=<unix socket file> like SSH does - if anyone ever uses that).

Simple connect without RELAY + E2EE?

Hello,

thanks for your great work. I noticed that the API changed and now it requires two tunnels (Relay + E2EE).

Is there any way to use the new wiretap in a mode how it used to be? A single tunnel between Client <-> Server without Relay+E2EE?

(I'm operating wiretap in a setting where I can only supply a single private + public key on the client (through an RPC interface) and there is no way to add two private and two public keys to achieve a E2EE tunnel inside a Relay tunnel. The last working wiretap that supports simple P2P tunnels seems to be v0.2.1)

TCP Keepalive not forwarded to upstream origin server.

It appears that wiretap does not send empty PSH packets (tcp keepalive) to check if the Origin-host still has the port open.

I'm using https://thc.org/segfault/wireguard with the wiretap v0.3.0 (--simple branch) with WIRETAP_SIMPLE=true ./wiretap_linux_amd64 serve --ipv4-relay 192.168.0.1 --ipv6-relay fd::1 --allowed 192.168.0.1/28,fd::1/125

The Exit Node is a Linux x86_64 running wiretap (WT-EXIT).
The origin host runs nmap -n -Pn -sT -p1-512 --open scanme.nmap.org

The Origin host sends a SYN to a host on the Internet that does not exist:

┌──(EXIT:Dirt)(root💀sf-BiologyMetal)-[~]
└─# nmap -n -Pn -sT -T5  -p80 --open 30.31.32.33

Observer on the Exit Node the state SYN-SENT for a long time even that the app (nmap) has long exited:

SYN-SENT 0      1       51.83.131.42:53150    30.31.32.33:80    users:(("wiretap_linux_a",pid=125616,fd=14))

The same bug (eg. lag of empty PSH for TCP KeepAlive between origin-host and WT-Exit) can be observed when starting an app on the upstream origin-server and not sending a FIN when killing the app (or that FIN drops on the wireguard/udp-leg):

In this case wiretap keeps the connection from the Exit Node to the target in ESTB "forever" even that the upstream app on the origin-server no longer has this connection open.

There are TCP Keepalive messages between wiretap and the target but there are no TCP keepalive between the wiretap and the upstream origin server.

A proposed solution would be to send an empty PSH (e.g. TCP KeepAlive) every 60 seconds from WT-EXIT to the upstream origin host and watch out for any returning RST or ICMP Dest unreachable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.