Skip to content

marten-seemann/docker-nat-simulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Docker NAT Simulator

For a hole-punching example, see the hole-punching branch.

The logic is loosely based on https://github.com/zzJinux/docker-nat-simulate, but it replaces all bash scripts used for setup with a Docker compose setup.

The setup only uses iptables to achieve NAT-ing.

Network Setup

  • The clients (192.168.0.0/16) are in a network that's assumed to be separate from the rest of the network by a NAT.
  • The server (17.0.0.100) is on the other side of the NAT. We intentionally use a public IP (see RFC 1918) here.
  • The router (192.168.0.42 and 17.0.0.42, respectively) acts as a NAT between these two networks.

Running

docker compose build && docker compose up

Validating the Setup

Using ping

Open a shell on one of the clients:

docker exec -it client /bin/bash

Then ping the server:

ping server

This works since the NAT is translating addresses from the internal network to the outside world.

Conversely, trying to ping the client from the server does not work, as we'd expect.

Open a shell on one of the server:

docker exec -it server /bin/bash

And try to ping the client:

ping 192.168.0.100

Simulating a network delay

Open a shell on the router (router) and add a delay:

tc qdisc add dev eth0 root netem delay 50ms

Now ping the server again from the client container. It's not clear to me why this results in an RTT of 50ms (and not 100ms) though.

Using netcat

While the ping test shows that basic connectivity is as we'd expect, it doesn't prove that we've actually built a NAT. For that, we'll use netcat.

Open a shell on the server, and start a server:

ncat -vk -l 80 -c 'xargs -n1 echo Echo from the server: '

Now in a separate terminal, open a shell on the first client, and establish a connection to the server:

ncat -v -p 45678 server 80

On the server side, we now see an incoming connection originating from 17.0.0.42:45678. It makes sense that we see the connection originating from the router (that's exacty what a NAT is supposed to do). It looks like iptables chose to preserve the port number.

To check that the NAT functions correctly, open a shell on the second client (client2), and establish another connection to the server, using the same source port:

ncat -v -p 45678 server 80

Now the NAT has no choice but to allocate a new port number, since both clients are using the same port. You should see an incoming connection on the server from a randomly allocated port number.

About

use Docker to simulate a NAT between Docker containers

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published