diff --git a/bin/mn b/bin/mn
index edd4d98423263ae1e8ca4955504ba83a180bac11..f4b16eff4cd947b6db628987de98632fc86233eb 100755
--- a/bin/mn
+++ b/bin/mn
@@ -200,6 +200,9 @@ class MininetRunner( object ):
         opts.add_option( '--pin', action='store_true',
                          default=False, help="pin hosts to CPU cores "
                          "(requires --host cfs or --host rt)" )
+        opts.add_option( '--nat', action='store_true',
+                         default=False, help="adds a NAT to the topology "
+                         "that connects Mininet to the physical network" )
         opts.add_option( '--version', action='callback', callback=version )
 
         self.options, self.args = opts.parse_args()
@@ -257,6 +260,10 @@ class MininetRunner( object ):
                   autoStaticArp=arp, autoPinCpus=pin,
                   listenPort=listenPort )
 
+        if self.options.nat:
+            nat = mn.addNAT()
+            nat.configDefault()
+
         if self.options.pre:
             CLI( mn, script=self.options.pre )
 
diff --git a/examples/natnet.py b/examples/natnet.py
new file mode 100755
index 0000000000000000000000000000000000000000..4305d1fc232d090c4488ce73a2b2dbd224d92386
--- /dev/null
+++ b/examples/natnet.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+"""
+natnet.py: Example network with NATs
+
+
+           h0
+           |
+           s0
+           |
+    ----------------
+    |              |
+   nat1           nat2
+    |              |
+   s1              s2
+    |              |
+   h1              h2 
+
+"""
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.nodelib import NAT
+from mininet.log import setLogLevel
+from mininet.cli import CLI
+from mininet.util import irange
+
+class InternetTopo(Topo):
+    "Single switch connected to n hosts."
+    def __init__(self, n=2, h=1, **opts):
+        Topo.__init__(self, **opts)
+
+        # set up inet switch
+        inetSwitch = self.addSwitch('s0')
+        # add inet host
+        inetHost = self.addHost('h0')
+        self.addLink(inetSwitch, inetHost)
+
+        # add local nets
+        for i in irange(1, n):
+            inetIntf = 'nat%d-eth0' % i
+            localIntf = 'nat%d-eth1' % i
+            localIP = '192.168.%d.1' % i
+            localSubnet = '192.168.%d.0/24' % i
+            natParams = { 'ip' : '%s/24' % localIP }
+            # add NAT to topology
+            nat = self.addNode('nat%d' % i, cls=NAT, subnet=localSubnet, 
+                               inetIntf=inetIntf, localIntf=localIntf)
+            switch = self.addSwitch('s%d' % i)
+            # connect NAT to inet and local switches
+            self.addLink(nat, inetSwitch, intfName1=inetIntf)
+            self.addLink(nat, switch, intfName1=localIntf, params1=natParams)
+            # add host and connect to local switch
+            host = self.addHost('h%d' % i, 
+                                ip='192.168.%d.100/24' % i, 
+                                defaultRoute='via %s' % localIP)
+            self.addLink(host, switch)
+
+def run():
+    "Create network and run the CLI"
+    topo = InternetTopo()
+    net = Mininet(topo=topo)
+    net.start()
+    CLI(net)
+    net.stop()
+
+if __name__ == '__main__':
+    setLogLevel('info')
+    run()
+    
\ No newline at end of file
diff --git a/examples/test/test_natnet.py b/examples/test/test_natnet.py
new file mode 100644
index 0000000000000000000000000000000000000000..3addc92e25e7f912887a90d5fbb77a55f491a201
--- /dev/null
+++ b/examples/test/test_natnet.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+"""
+Test for natnet.py
+"""
+
+import unittest
+import pexpect
+from mininet.util import quietRun
+
+class testNATNet( unittest.TestCase ):
+
+    prompt = 'mininet>'
+
+    def setUp( self ):
+        self.net = pexpect.spawn( 'python -m mininet.examples.natnet' )
+        self.net.expect( self.prompt )
+
+    def testPublicPing( self ):
+        "Attempt to ping the public server (h0) from h1 and h2"
+        self.net.sendline( 'h1 ping -c 1 h0' )
+        self.net.expect ( '(\d+)% packet loss' )
+        percent = int( self.net.match.group( 1 ) ) if self.net.match else -1
+        self.assertEqual( percent, 0 )
+        self.net.expect( self.prompt )
+
+        self.net.sendline( 'h2 ping -c 1 h0' )
+        self.net.expect ( '(\d+)% packet loss' )
+        percent = int( self.net.match.group( 1 ) ) if self.net.match else -1
+        self.assertEqual( percent, 0 )
+        self.net.expect( self.prompt )
+
+    def testPrivatePing( self ):
+        "Attempt to ping h1 and h2 from public server"
+        self.net.sendline( 'h0 ping -c 1 -t 1 h1' )
+        result = self.net.expect ( [ 'unreachable', 'loss' ] )
+        self.assertEqual( result, 0 )
+        self.net.expect( self.prompt )
+
+        self.net.sendline( 'h0 ping -c 1 -t 1 h2' )
+        result = self.net.expect ( [ 'unreachable', 'loss' ] )
+        self.assertEqual( result, 0 )
+        self.net.expect( self.prompt )
+
+    def testPrivateToPrivatePing( self ):
+        "Attempt to ping from NAT'ed host h1 to NAT'ed host h2"
+        self.net.sendline( 'h1 ping -c 1 -t 1 h2' )
+        result = self.net.expect ( [ '[Uu]nreachable', 'loss' ] )
+        self.assertEqual( result, 0 )
+        self.net.expect( self.prompt )
+
+    def tearDown( self ):
+        self.net.sendline( 'exit' )
+        self.net.wait()
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/mininet/net.py b/mininet/net.py
index 80654f5c37583cd341da02fb25375e6bb3c23f45..880780401847226905b183a4ddf1a791c3b70f0e 100755
--- a/mininet/net.py
+++ b/mininet/net.py
@@ -97,6 +97,7 @@
 from mininet.cli import CLI
 from mininet.log import info, error, debug, output, warn
 from mininet.node import Host, OVSKernelSwitch, DefaultController, Controller
+from mininet.nodelib import NAT
 from mininet.link import Link, Intf
 from mininet.util import quietRun, fixLimits, numCores, ensureRoot
 from mininet.util import macColonHex, ipStr, ipParse, netParse, ipAdd
@@ -208,7 +209,7 @@ def addHost( self, name, cls=None, **params ):
                                   prefixLen=self.prefixLen ) +
                                   '/%s' % self.prefixLen }
         if self.autoSetMacs:
-            defaults[ 'mac'] = macColonHex( self.nextIP )
+            defaults[ 'mac' ] = macColonHex( self.nextIP )
         if self.autoPinCpus:
             defaults[ 'cores' ] = self.nextCore
             self.nextCore = ( self.nextCore + 1 ) % self.numCores
@@ -260,6 +261,20 @@ def addController( self, name='c0', controller=None, **params ):
             self.nameToNode[ name ] = controller_new
         return controller_new
 
+    def addNAT( self, name='nat0', connect=True, inNamespace=False, **params ):
+        nat = self.addHost( name, cls=NAT, inNamespace=inNamespace, 
+                            subnet=self.ipBase, **params )
+        # find first switch and create link
+        if connect:
+            # connect the nat to the first switch
+            self.addLink( nat, self.switches[ 0 ] )
+            # set the default route on hosts
+            natIP = nat.params[ 'ip' ].split('/')[ 0 ]
+            for host in self.hosts:
+                if host.inNamespace:
+                    host.setDefaultRoute( 'via %s' % natIP )
+        return nat
+
     # BL: We now have four ways to look up nodes
     # This may (should?) be cleaned up in the future.
     def getNodeByName( self, *args ):
diff --git a/mininet/node.py b/mininet/node.py
index 55d353104ad1cefecb38da4ae45e03ebffdaf3bc..7eb632217774fa76b0979d560569e1826b2c9814 100644
--- a/mininet/node.py
+++ b/mininet/node.py
@@ -1358,7 +1358,6 @@ def checkListening( self ):
             warn( "Unable to contact the remote controller"
                   " at %s:%d\n" % ( self.ip, self.port ) )
 
-
 def DefaultController( name, order=[ Controller, OVSController ], **kwargs ):
     "find any controller that is available and run it"
     for controller in order:
diff --git a/mininet/nodelib.py b/mininet/nodelib.py
index 2eb80465cd005c28c9a2aaa86aa920b2cc04c02a..1760c7b30b761cf143e1f04d71bc3b6714ea9ec4 100644
--- a/mininet/nodelib.py
+++ b/mininet/nodelib.py
@@ -1,15 +1,12 @@
 """
 Node Library for Mininet
 
-This contains additional Node types which you may find to be useful
+This contains additional Node types which you may find to be useful.
 """
 
-from mininet.net import Mininet
-from mininet.topo import Topo
-from mininet.node import Switch
+from mininet.node import Node, Switch
 from mininet.log import setLogLevel, info
 
-
 class LinuxBridge( Switch ):
     "Linux Bridge (with optional spanning tree)"
 
@@ -49,3 +46,70 @@ def stop( self ):
         self.cmd( 'ifconfig', self, 'down' )
         self.cmd( 'brctl delbr', self )
 
+class NAT( Node ):
+    """NAT: Provides connectivity to external network"""
+
+    def __init__( self, name, inetIntf='eth0', subnet='10.0/8', localIntf=None, **params):
+        super( NAT, self ).__init__( name, **params )
+
+        """Start NAT/forwarding between Mininet and external network
+        inetIntf: interface for internet access
+        subnet: Mininet subnet (default 10.0/8)="""
+        self.inetIntf = inetIntf
+        self.subnet = subnet
+        self.localIntf = localIntf
+
+    def config( self, **params ):
+        super( NAT, self).config( **params )
+        """Configure the NAT and iptables"""
+
+        if not self.localIntf:
+            self.localIntf =  self.defaultIntf()
+
+        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
+
+        # Flush any currently active rules
+        # TODO: is this safe?
+        self.cmd( 'iptables -F' )
+        self.cmd( 'iptables -t nat -F' )
+
+        # Create default entries for unmatched traffic
+        self.cmd( 'iptables -P INPUT ACCEPT' )
+        self.cmd( 'iptables -P OUTPUT ACCEPT' )
+        self.cmd( 'iptables -P FORWARD DROP' )
+
+        # Configure NAT
+        self.cmd( 'iptables -I FORWARD -i', self.localIntf, '-d', self.subnet, '-j DROP' )
+        self.cmd( 'iptables -A FORWARD -i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
+        self.cmd( 'iptables -A FORWARD -i', self.inetIntf, '-d', self.subnet, '-j ACCEPT' )
+        self.cmd( 'iptables -t nat -A POSTROUTING -o ', self.inetIntf, '-j MASQUERADE' )
+
+        # Instruct the kernel to perform forwarding
+        self.cmd( 'sysctl net.ipv4.ip_forward=1' )
+
+        # Prevent network-manager from messing with our interface
+        # by specifying manual configuration in /etc/network/interfaces
+        intf = self.localIntf
+        cfile = '/etc/network/interfaces'
+        line = '\niface %s inet manual\n' % intf
+        config = open( cfile ).read()
+        if ( line ) not in config:
+            info( '*** Adding "' + line.strip() + '" to ' + cfile )
+            with open( cfile, 'a' ) as f:
+                f.write( line )
+        # Probably need to restart network-manager to be safe -
+        # hopefully this won't disconnect you
+        self.cmd( 'service network-manager restart' )
+
+    def terminate( self ):
+        """Stop NAT/forwarding between Mininet and external network"""
+        # Flush any currently active rules
+        # TODO: is this safe?
+        self.cmd( 'iptables -F' )
+        self.cmd( 'iptables -t nat -F' )
+
+        # Instruct the kernel to stop forwarding
+        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
+
+        super( NAT, self ).terminate()
+