faking services on an entire IP subnet – part II (L3 NAT and fake services in docker)

In our last post, we used a new L2 OVS proxy to fake TCP services on an entire IP subnet. We used network namespaces for isolation. However, using namespaces can make running fake services under docker somewhat inconvenient. So this time around, we’re going to have pipette do L3 NAT for us as well, so we can just attach services as we please. We’re going to fake a webserver on port 80 (as docker based webservers are easy to come by).

We are using the same physical setup as last time. However, we are now using a slightly different FAUCET ACL. We are going to work with TCP port 80 only, and only on Note that we are also instructing FAUCET to always add a VLAN VID tag when it dispatches the intercepted traffic to the coprocessor (not strictly necessary but does make things more consistent).

  - rule:
      dl_type: 0x800
      ip_proto: 6
      tcp_dst: 80
          vlan_vid: 2
          ports: [18]
  - rule:
        allow: 1

We’ll also need a new version of pipette – this one is a bit smarter – it can do L3 NAT. Specifically, it will NAT to on the coprocessor. That way we can just run services that listen on, and they’ll appear in the real network, magically with the right MAC addresses.

We’ll start pipette like this:


# interface connected to FAUCET coprocessor port.
# interface that will be created for fake services to run on.
# Reserved MAC addresses for fake services to use to talk to clients.
# address fake services will be run on (will be proxied from real IPs)
# OVS bridge name
# pipette OF port

# Configure pipette's OVS switch.
# Remove all IP addresses, disable IPv6.
ip link add dev $FAKEINT type veth peer name ovs$FAKEINT
for i in $COPROINT $FAKEINT ovs$FAKEINT ovs-system ; do
  echo 1 > /proc/sys/net/ipv6/conf/$i/disable_ipv6
  ifconfig $i
ifconfig $COPROINT up
ifconfig ovs$FAKEINT up
ifconfig $FAKEINT hw ether $FAKEHW $FAKEIP up
ovs-vsctl del-br $BR 
ovs-vsctl add-br $BR
ovs-ofctl del-flows $BR
for i in $COPROINT ovs$FAKEINT ; do
  ovs-vsctl add-port $BR $i
ovs-vsctl set-controller $BR tcp:$OF

# Run pipette.
ryu-manager pipette.py --ofp-tcp-listen-port $OF  --verbose

Now, we can start a webserver on

pi@coprocessor:~ $ docker run -d -p hypriot/rpi-busybox-httpd
pi@coprocessor:~ $ docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                      NAMES
89425b1198b3        hypriot/rpi-busybox-httpd   "/bin/busybox httpd …"   11 seconds ago      Up 9 seconds>80/tcp   keen_goldberg

Now all it remains for us to do, is from outside the coprocessor, try to access the webserver “allegedly” running on

pi@pi8021x:~ $ wget -q -O- 80
<head><title>Pi armed with Docker by Hypriot</title>
  <body style="width: 100%; background-color: black;">
    <div id="main" style="margin: 100px auto 0 auto; width: 800px;">
      <img src="pi_armed_with_docker.jpg" alt="pi armed with docker" style="width: 800px">

With pipette now doing L3 NAT, we can start pretty much whatever services we like listening on fake0, and provided we use the right FAUCET ACL to intercept the traffic, those services will appear in the dataplane.