Viewing WireGuard Traffic with TcpdumpPublished on
Part of the Wireguard series:
- WireGuard VPN Walkthrough
- Routing Select Docker Containers through Wireguard VPN
- Viewing WireGuard Traffic with Tcpdump
- Leaning on Algo to route Docker traffic through Wireguard (most recent and consolidates the previous articles)
On the article, WireGuard VPN Walkthrough, Glen posted the tantalizing question:
How would you verify/confirm that the link is definitely encrypted? If you use OpenVPN and use Wireshark to sniff the packets, you see the OPENVPN protocol listed in the captured dump. Is there an equivalent for Wireguard?
For testing, here are my assumptions:
- External Wireguard server is hosted at IP address 100.100.100.100
- Local Wireguard interface is called
10.192.122.2. We won’t be using
wg-quick(see solution #2 if you want to setup the interface and follow along)
curl --interface eth0 http://httpbin.org/ipgives your external ip address (126.96.36.199)
curl --interface wg1 http://httpbin.org/ipgives vpn ip address (100.100.100.100)
- If we can observe unencrypted data while listening to
eth0then the connection is not secure.
Plain HTTP is not secure so let’s watch for our request to httpbin. We’ll be able to snoop using
eth0 curl statement, we’ll be able to clearly see our HTTP request and response:
- We see our
eth0address (192.168.1.6) talking to httpbin’s server at 188.8.131.52
- The response contains our expected external ip address (184.108.40.206)
- And oh no, we’re snooping!
Let’s look at what executing the
wg1 curl will look like with:
- We see our
wg1address (10.192.122.2) talking to httpbin’s server at 220.127.116.11
- The response contains our VPN’s external ip address (100.100.100.100)
- And oh no, we’re snooping! Or are we?
Don’t worry, in this example we’re sending plaintext to a Wireguard interface and receiving plaintext back, which is what our
tcpdump command is showing. However, our Wireguard interface doesn’t actually have the capability to send network data anywhere. It’ll have
eth0 transmit the encrypted payload to our VPN server. This means that listening on
eth0 but executing the
wg1 curl will show encrypted contents. If
eth0 can’t read the contents then no one else will either.
We’ll update our tcpdump command as we won’t be communicating TCP over port 80. We know we’ll be communicating with our VPN server, so only capture traffic between us and the server.
Since we’ll be seeing encrypted packets, they won’t be printable. To display the contents, we’ll view the data hex encoded (which is the
I’ve also removed the IPv4 header and UDP header, so we can just focus on the data. Below is the our
HTTP GET request.
Notice that the data starts with
0400 0000. If we cross reference this with Wireguard’s documented protocol, we can confirm that the data begins with an 8bit
4 followed by 24 bits of 0, so we can rest assured that we’ve set up Wireguard correctly. One could dig a little deeper in the subsequent bits to capture the receiver index part of the protocol, but as a heuristic,
0400 0000 is decent. Keep in mind Wireguard doesn’t try to obsfuscate data, so an internet provider could reasonably try to detect and block Wireguard traffic.
The creator of wireguard had this to say:
WireGuard does not aim to evade DPS [deep packet inspection], unfortunately. There are several things that prevent this from occurring:
- The first byte, which is a fixed
- The fact that
mac2is most often all zeros.
- The fixed length of handshake messages.
- The unencrypted ephemeral public key.
So Wireguard isn’t the panacea for those trying to evade sophisticated and unfriendly firewalls (and Wireguard never billed itself as that). It’s a great VPN that can be combined with other tools to match one’s desired needs.