mininet / examples / nat.py @ 7c5d2771
History | View | Annotate | Download (3.77 KB)
1 | 3484389d | Bob Lantz | #!/usr/bin/python
|
---|---|---|---|
2 | |||
3 | """
|
||
4 | Example to create a Mininet topology and connect it to the internet via NAT
|
||
5 | through eth0 on the host.
|
||
6 |
|
||
7 | Glen Gibb, February 2011
|
||
8 |
|
||
9 | (slight modifications by BL, 5/13)
|
||
10 | """
|
||
11 | |||
12 | from mininet.cli import CLI |
||
13 | 33e39a24 | Bob Lantz | from mininet.log import lg |
14 | 3484389d | Bob Lantz | from mininet.node import Node |
15 | from mininet.topolib import TreeNet |
||
16 | |||
17 | #################################
|
||
18 | def startNAT( root, inetIntf='eth0', subnet='10.0/8' ): |
||
19 | """Start NAT/forwarding between Mininet and external network
|
||
20 | root: node to access iptables from
|
||
21 | inetIntf: interface for internet access
|
||
22 | subnet: Mininet subnet (default 10.0/8)="""
|
||
23 | |||
24 | # Identify the interface connecting to the mininet network
|
||
25 | localIntf = root.defaultIntf() |
||
26 | |||
27 | # Flush any currently active rules
|
||
28 | root.cmd( 'iptables -F' )
|
||
29 | root.cmd( 'iptables -t nat -F' )
|
||
30 | |||
31 | # Create default entries for unmatched traffic
|
||
32 | root.cmd( 'iptables -P INPUT ACCEPT' )
|
||
33 | root.cmd( 'iptables -P OUTPUT ACCEPT' )
|
||
34 | root.cmd( 'iptables -P FORWARD DROP' )
|
||
35 | |||
36 | # Configure NAT
|
||
37 | root.cmd( 'iptables -I FORWARD -i', localIntf, '-d', subnet, '-j DROP' ) |
||
38 | root.cmd( 'iptables -A FORWARD -i', localIntf, '-s', subnet, '-j ACCEPT' ) |
||
39 | root.cmd( 'iptables -A FORWARD -i', inetIntf, '-d', subnet, '-j ACCEPT' ) |
||
40 | root.cmd( 'iptables -t nat -A POSTROUTING -o ', inetIntf, '-j MASQUERADE' ) |
||
41 | |||
42 | # Instruct the kernel to perform forwarding
|
||
43 | root.cmd( 'sysctl net.ipv4.ip_forward=1' )
|
||
44 | |||
45 | def stopNAT( root ): |
||
46 | """Stop NAT/forwarding between Mininet and external network"""
|
||
47 | # Flush any currently active rules
|
||
48 | root.cmd( 'iptables -F' )
|
||
49 | root.cmd( 'iptables -t nat -F' )
|
||
50 | |||
51 | # Instruct the kernel to stop forwarding
|
||
52 | root.cmd( 'sysctl net.ipv4.ip_forward=0' )
|
||
53 | |||
54 | def fixNetworkManager( root, intf ): |
||
55 | """Prevent network-manager from messing with our interface,
|
||
56 | by specifying manual configuration in /etc/network/interfaces
|
||
57 | root: a node in the root namespace (for running commands)
|
||
58 | intf: interface name"""
|
||
59 | cfile = '/etc/network/interfaces'
|
||
60 | line = '\niface %s inet manual\n' % intf
|
||
61 | config = open( cfile ).read()
|
||
62 | 824afb84 | Rémy Léone | if line not in config: |
63 | 3484389d | Bob Lantz | print '*** Adding', line.strip(), 'to', cfile |
64 | with open( cfile, 'a' ) as f: |
||
65 | f.write( line ) |
||
66 | e7712396 | Bob Lantz | # Probably need to restart network-manager to be safe -
|
67 | # hopefully this won't disconnect you
|
||
68 | root.cmd( 'service network-manager restart' )
|
||
69 | 3484389d | Bob Lantz | |
70 | def connectToInternet( network, switch='s1', rootip='10.254', subnet='10.0/8'): |
||
71 | """Connect the network to the internet
|
||
72 | switch: switch to connect to root namespace
|
||
73 | rootip: address for interface in root namespace
|
||
74 | subnet: Mininet subnet"""
|
||
75 | switch = network.get( switch ) |
||
76 | prefixLen = subnet.split( '/' )[ 1 ] |
||
77 | |||
78 | # Create a node in root namespace
|
||
79 | root = Node( 'root', inNamespace=False ) |
||
80 | |||
81 | # Prevent network-manager from interfering with our interface
|
||
82 | fixNetworkManager( root, 'root-eth0' )
|
||
83 | |||
84 | # Create link between root NS and switch
|
||
85 | link = network.addLink( root, switch ) |
||
86 | link.intf1.setIP( rootip, prefixLen ) |
||
87 | |||
88 | # Start network that now includes link to root namespace
|
||
89 | network.start() |
||
90 | |||
91 | # Start NAT and establish forwarding
|
||
92 | startNAT( root ) |
||
93 | |||
94 | # Establish routes from end hosts
|
||
95 | for host in network.hosts: |
||
96 | host.cmd( 'ip route flush root 0/0' )
|
||
97 | host.cmd( 'route add -net', subnet, 'dev', host.defaultIntf() ) |
||
98 | host.cmd( 'route add default gw', rootip )
|
||
99 | |||
100 | return root
|
||
101 | |||
102 | if __name__ == '__main__': |
||
103 | lg.setLogLevel( 'info')
|
||
104 | net = TreeNet( depth=1, fanout=4 ) |
||
105 | # Configure and start NATted connectivity
|
||
106 | rootnode = connectToInternet( net ) |
||
107 | print "*** Hosts are running and should have internet connectivity" |
||
108 | print "*** Type 'exit' or control-D to shut down network" |
||
109 | CLI( net ) |
||
110 | # Shut down NAT
|
||
111 | stopNAT( rootnode ) |
||
112 | net.stop() |