Changes between Initial Version and Version 1 of GENIExperimenter/Tutorials/OpenFlowNetworkDevices/NAT


Ignore:
Timestamp:
07/11/15 15:12:13 (9 years ago)
Author:
sedwards@bbn.com
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • GENIExperimenter/Tutorials/OpenFlowNetworkDevices/NAT

    v1 v1  
     1= OpenFlow NAT Router =
     2
     3
     4In this section, we are going to build a router for a network with a private address space that needs a one-to-many NAT (IP Masquerade) for some reason (e.g. short on public IP space or security) using OpenFlow. As shown in the figure below, hosts `inside1` and `inside2` are part of the private network, while host `outside` is outside. The LAN has only one public IP — '''128.128.129.1'''. (The external IPs we use, 128.128.128.0/24 and 128.128.129.0/24, are just an example. If your public IP happens to be in this subnet, change them to others.)
     5
     6[[Image(openflow-nat.png, 50%, nolink)]] 
     7== 1 Test reachability before starting controller ==
     8=== 1.1 Login to your hosts ===
     9
     10To start our experiment we need to ssh into all of our hosts. Depending on which tool and OS you are using there is a slightly different process for logging in. If you don't know how to SSH to your reserved hosts take a look in [wiki:HowTo/LoginToNodes this page.] Once you have logged in, follow the rest of the instructions.
     11
     12=== 1.2 Test reachability ===
     13
     14a. First we start a ping from `inside1` to `inside2`, which should work since they are both inside the same LAN.
     15{{{
     16inside1:~$ ping 192.168.0.3 -c 10
     17}}}
     18
     19b. Then we start a ping from `outside` to `inside1`, which should timeout as there is no routing information in its routing table. You can use `route -n` to verify that.
     20{{{
     21outside:~$ ping 192.168.0.2 -c 10
     22}}}
     23
     24c. Similarly, we cannot ping from `insideX` to `outside`.
     25
     26d. You can also use Netcat (`nc`) to test reachability of TCP and UDP. The behavior should be the same.
     27
     28== 2 Start controller to enable NAT ==
     29
     30=== 2.1 Access a server from behind the NAT ===
     31
     32You can try to write your own controller to implement NAT. However, we've provided you a functional controller, which is a file called `nat.py` under `/tmp/ryu/` .
     33
     34a. Start the controller on `NAT` host:
     35{{{
     36nat:~$ cd /tmp/ryu/
     37nat:~$ ./bin/ryu-manager nat.py
     38}}}
     39You should see output similar to following log after the switch is connected to the controller
     40{{{
     41loading app nat.py
     42loading app ryu.controller.dpset
     43loading app ryu.controller.ofp_handler
     44instantiating app ryu.controller.dpset of DPSet
     45instantiating app ryu.controller.ofp_handler of OFPHandler
     46instantiating app nat.py of NAT
     47switch connected <ryu.controller.controller.Datapath object at 0x2185210>
     48}}}
     49
     50
     51b. On `outside`, we start a nc server:
     52{{{
     53outside:~$ nc -l 6666
     54}}}
     55and we start a nc client on `inside1` to connect it:
     56{{{
     57inside1:~$ nc 128.128.128.2 6666
     58}}}
     59
     60c. Now send message between each other and try the same thing between `outside` and `inside2`.
     61
     62d. On the terminal of `switch`, in which you started your controller, you should see a log similar to:
     63{{{
     64Created mapping 192.168.0.3 31596 to 128.128.129.1 59997
     65}}}
     66Note that there should be only one log per connection, because the rest of the communication will re-use the mapping.
     67
     68{{{
     69#!comment
     70=== 2.2 Outside source ===
     71
     72You may be wondering whether it will behave the same if we use `insideX` hosts to be the nc server. You can try it and the answer is no. That's due to the nature of dynamic NAT.
     73
     74However, it will work if we can access the translation table on the switch.
     75
     76a. Look back into the log we got previously:
     77{{{
     78Created mapping 192.168.0.3 31596 to 128.128.129.1 59997
     79}}}
     80Now we know there is mapping between these two pairs.
     81
     82b. Now we start a nc server on `inside2` (`inside1` if your mapping shows 192.168.0.2) on the according port:
     83{{{
     84inside2:~$ nc -l 31596
     85}}}
     86
     87c. Then on `outside`, we start a nc client:
     88{{{
     89outside:~$ nc 128.128.128.1 59997
     90}}}
     91
     92d. `outside` and `inside2` should be able to send messages to each other.
     93
     94e. Common solution of handling outside source is providing some way to manually create mapping in advance. We will leave it as an exercise for you to implement it.
     95}}}
     96
     97== 3 Handle ARP and ICMP ==
     98One of very common mistakes that people make, when writing OF controller, is forgetting to handle ARP and ICMP message and finding their controller does not work as expected.
     99
     100=== 3.1 ARP ===
     101As we mentioned before, we should insert rules into the OF switch that allow ARP packets to go through, probably after the switch is connected.
     102
     103=== 3.2 ICMP ===
     104Handling ARP is trivial as NAT does not involve ARP. However, it's not the case for ICMP. If you only process translation for TCP/UDP, you will find you cannot ping between `outside` and `insideX` while nc is working properly. Handling ICMP is even not as straightforward as for TCP/UDP. Because for ICMP, you cannot get port information to bind with. Our provided solution makes use of ICMP echo identifier. You may come up with different approach involves ICMP sequence number or others.
     105
     106a. On `inside1`, start a ping to `outside`.
     107{{{
     108inside1:~$ ping 128.128.128.2
     109}}}
     110
     111b. Do the same thing on `inside2`.
     112{{{
     113inside2:~$ ping 128.128.128.2
     114}}}
     115
     116You should see both pinging are working.
     117
     118c. On `outside`, use `tcpdump` to check the packets it receives.
     119{{{
     120outside:~$ sudo tcpdump -i eth1
     121}}}
     122
     123You should see it's receiving two groups of icmp packets, differentiated by icmp_id.