diff options
| author | Vishvananda Ishaya <vishvananda@gmail.com> | 2013-05-20 09:39:59 -0700 |
|---|---|---|
| committer | Vishvananda Ishaya <vishvananda@gmail.com> | 2013-06-04 13:56:42 -0700 |
| commit | 769782be844e4c74fdc0aad0ff704b06c874c3ad (patch) | |
| tree | 862f0769eea370ecb401d114968d64daf96de018 /nova | |
| parent | 55ccdbc3bc62dc32161112a77c0fed39e73ee7b4 (diff) | |
Don't snat all traffic when force_snat_range set
When using /proc/sys/net/bridge/bridge-nf-call-iptables=1, bridged
traffic gets snatted even though it is being bridged out to an
external gateway. This can lead to asymmetric routes where traffic
goes out the fixed network and comes back on the float network
and can lead to packets being blocked by firewalls. Work around
this problem by only fallback snatting when the traffic is
going to one of the force_snat_ranges. If force_snat_range is not
set it defaults to the existing behavior of snatting all traffic
that doesn't hit an earlier rule.
Fixes bug 1182143
Change-Id: If496dad2308a68a6a4a9fd43d695943bc5034ac4
Diffstat (limited to 'nova')
| -rw-r--r-- | nova/network/linux_net.py | 11 | ||||
| -rw-r--r-- | nova/tests/network/test_linux_net.py | 22 | ||||
| -rw-r--r-- | nova/tests/network/test_manager.py | 18 |
3 files changed, 39 insertions, 12 deletions
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index c47b50060..9156c3306 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -628,11 +628,12 @@ def metadata_accept(): def add_snat_rule(ip_range): if CONF.routing_source_ip: - rule = '-s %s -j SNAT --to-source %s' % (ip_range, - CONF.routing_source_ip) - if CONF.public_interface: - rule += ' -o %s' % CONF.public_interface - iptables_manager.ipv4['nat'].add_rule('snat', rule) + for dest_range in CONF.force_snat_range or ['0.0.0.0/0']: + rule = ('-s %s -d %s -j SNAT --to-source %s' + % (ip_range, dest_range, CONF.routing_source_ip)) + if CONF.public_interface: + rule += ' -o %s' % CONF.public_interface + iptables_manager.ipv4['nat'].add_rule('snat', rule) iptables_manager.apply() diff --git a/nova/tests/network/test_linux_net.py b/nova/tests/network/test_linux_net.py index 4829f2d93..e9542a648 100644 --- a/nova/tests/network/test_linux_net.py +++ b/nova/tests/network/test_linux_net.py @@ -242,6 +242,28 @@ class LinuxNetworkTestCase(test.TestCase): self.stubs.Set(db, 'instance_get', get_instance) self.stubs.Set(db, 'network_get_associated_fixed_ips', get_associated) + def _test_add_snat_rule(self, expected): + def verify_add_rule(chain, rule): + self.assertEqual(chain, 'snat') + self.assertEqual(rule, expected) + + self.stubs.Set(linux_net.iptables_manager.ipv4['nat'], + 'add_rule', verify_add_rule) + linux_net.add_snat_rule('10.0.0.0/24') + + def test_add_snat_rule(self): + self.flags(routing_source_ip='10.10.10.1') + expected = ('-s 10.0.0.0/24 -d 0.0.0.0/0 ' + '-j SNAT --to-source 10.10.10.1 -o eth0') + self._test_add_snat_rule(expected) + + def test_add_snat_rule_snat_range(self): + self.flags(routing_source_ip='10.10.10.1', + force_snat_range=['10.10.10.0/24']) + expected = ('-s 10.0.0.0/24 -d 10.10.10.0/24 ' + '-j SNAT --to-source 10.10.10.1 -o eth0') + self._test_add_snat_rule(expected) + def test_update_dhcp_for_nw00(self): self.flags(use_single_default_gateway=True) diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index b8f75233a..1fa578aaf 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -1710,7 +1710,8 @@ class CommonNetworkTestCase(test.TestCase): table_name='nat') # The expected rules that should be configured based on the fixed_range - expected_lines = ['[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o %s' + expected_lines = ['[0:0] -A %s-snat -s %s -d 0.0.0.0/0 ' + '-j SNAT --to-source %s -o %s' % (binary_name, CONF.fixed_range, CONF.routing_source_ip, CONF.public_interface), @@ -1758,7 +1759,8 @@ class CommonNetworkTestCase(test.TestCase): table_name='nat') # The expected rules that should be configured based on the fixed_range - expected_lines = ['[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o %s' + expected_lines = ['[0:0] -A %s-snat -s %s -d 0.0.0.0/0 ' + '-j SNAT --to-source %s -o %s' % (binary_name, networks[0]['cidr'], CONF.routing_source_ip, CONF.public_interface), @@ -1772,7 +1774,8 @@ class CommonNetworkTestCase(test.TestCase): '--ctstate DNAT -j ACCEPT' % (binary_name, networks[0]['cidr'], networks[0]['cidr']), - '[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o %s' + '[0:0] -A %s-snat -s %s -d 0.0.0.0/0 ' + '-j SNAT --to-source %s -o %s' % (binary_name, networks[1]['cidr'], CONF.routing_source_ip, CONF.public_interface), @@ -1826,10 +1829,11 @@ class CommonNetworkTestCase(test.TestCase): table_name='nat') # Add the new expected rules to the old ones - expected_lines += ['[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o ' - '%s' % (binary_name, new_network['cidr'], - CONF.routing_source_ip, - CONF.public_interface), + expected_lines += ['[0:0] -A %s-snat -s %s -d 0.0.0.0/0 ' + '-j SNAT --to-source %s -o %s' + % (binary_name, new_network['cidr'], + CONF.routing_source_ip, + CONF.public_interface), '[0:0] -A %s-POSTROUTING -s %s -d %s/32 -j ACCEPT' % (binary_name, new_network['cidr'], CONF.metadata_host), |
