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 192.168.2.0/24. 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).
acls: coprocessssh: - rule: dl_type: 0x800 ip_proto: 6 ipv4_src: 192.168.2.0/24 ipv4_dst: 192.168.2.0/24 tcp_dst: 80 actions: output: vlan_vid: 2 ports:  - rule: actions: 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 192.168.2.0/24 to 192.168.101.0/24 on the coprocessor. That way we can just run services that listen on 192.168.101.1/24, and they’ll appear in the real 192.168.2.0/24 network, magically with the right MAC addresses.
We’ll start pipette like this:
#!/bin/bash # interface connected to FAUCET coprocessor port. COPROINT=enx0023565c8859 # interface that will be created for fake services to run on. FAKEINT=fake0 # Reserved MAC addresses for fake services to use to talk to clients. FAKEHW=0e:00:00:00:00:66 FAKECLIENTHW=0e:00:00:00:00:67 # address fake services will be run on (will be proxied from real IPs) FAKEIP=192.168.101.1/24 # OVS bridge name BR=copro0 # pipette OF port OF=6699 # 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 0.0.0.0 done 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 done ovs-vsctl set-controller $BR tcp:127.0.0.1:$OF # Run pipette. ryu-manager pipette.py --ofp-tcp-listen-port $OF --verbose
Now, we can start a webserver on 192.168.101.1:
pi@coprocessor:~ $ docker run -d -p 192.168.101.1:80:80 hypriot/rpi-busybox-httpd 89425b1198b3eb30267f05fa10bc3691efc7b36710297e4695030705ee09c9bb 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 192.168.101.1:80->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 192.168.2.1:
pi@pi8021x:~ $ wget -q -O- 192.168.2.1 80 <html> <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"> </div> </body> </html>
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.