summaryrefslogtreecommitdiff
path: root/roles/colo-router
diff options
context:
space:
mode:
authorAndy Doan <andy.doan@linaro.org>2016-02-29 16:13:55 -0600
committerAndy Doan <andy.doan@linaro.org>2016-03-23 11:00:44 -0500
commit7c309492eaed0e625f94d9c0a93a6f6733c47008 (patch)
tree8bdb4244472cd9e15959140243f4aa389f7c039e /roles/colo-router
parentc7d7177b3df2302cbd8dae60dd6716bf00cde798 (diff)
colo: add a way to better manage public/private ip mappings
This just does public/private ips for now, but could probably be expanded to also handle our subnet logic as well. Change-Id: If0648142ee91d04b102078cdf2a93b84780f6f4a
Diffstat (limited to 'roles/colo-router')
-rw-r--r--roles/colo-router/files/iptables13
-rw-r--r--roles/colo-router/files/iptables.conf19
-rwxr-xr-xroles/colo-router/files/manage_iptables.py116
-rw-r--r--roles/colo-router/handlers/main.yml3
-rw-r--r--roles/colo-router/tasks/main.yml16
5 files changed, 153 insertions, 14 deletions
diff --git a/roles/colo-router/files/iptables b/roles/colo-router/files/iptables
index 4fda4f76..4960691a 100644
--- a/roles/colo-router/files/iptables
+++ b/roles/colo-router/files/iptables
@@ -8,18 +8,7 @@ subnets="10.10.0.0/16 10.20.0.0/16 10.30.0.0/16 10.33.0.0/16"
modprobe iptable_nat
-# perform routing of r1-a1 with a public ip
-iptables -t nat -A PREROUTING -d 64.28.108.83 -j DNAT --to-destination 10.64.0.101
-iptables -t nat -A POSTROUTING -s 10.64.0.101 -j SNAT --to 64.28.108.83
-# perform routing of r1-a2 with a public ip
-iptables -t nat -A PREROUTING -d 64.28.108.84 -j DNAT --to-destination 10.64.0.102
-iptables -t nat -A POSTROUTING -s 10.64.0.102 -j SNAT --to 64.28.108.84
-# perform routing of r1-a3 with a public ip
-iptables -t nat -A PREROUTING -d 64.28.108.85 -j DNAT --to-destination 10.64.0.103
-iptables -t nat -A POSTROUTING -s 10.64.0.103 -j SNAT --to 64.28.108.85
-# perform routing of r1-a21 (git-atx) with a public ip
-iptables -t nat -A PREROUTING -d 64.28.108.189 -j DNAT --to-destination 10.10.0.121
-iptables -t nat -A POSTROUTING -s 10.10.0.121 -j SNAT --to 64.28.108.189
+/usr/local/bin/manage_iptables.py sync
for subnet in $subnets ; do
iptables -t nat -A POSTROUTING -s $subnet -o $ext -j MASQUERADE
diff --git a/roles/colo-router/files/iptables.conf b/roles/colo-router/files/iptables.conf
new file mode 100644
index 00000000..85a500a8
--- /dev/null
+++ b/roles/colo-router/files/iptables.conf
@@ -0,0 +1,19 @@
+[public/private mappings]
+# r1-a1
+64.28.108.83 = 10.64.0.101
+# r1-a2
+64.28.108.84 = 10.64.0.102
+# r1-a3
+64.28.108.85 = 10.64.0.103
+
+# r1-a21 (weechat.linaro.org)
+64.28.108.189 = 10.10.0.121
+
+#64.28.99.27
+#64.28.99.28
+#64.28.99.29
+#64.28.99.30
+#64.28.99.31
+#64.28.99.32
+#64.28.99.33
+#64.28.99.34
diff --git a/roles/colo-router/files/manage_iptables.py b/roles/colo-router/files/manage_iptables.py
new file mode 100755
index 00000000..ffa9b68e
--- /dev/null
+++ b/roles/colo-router/files/manage_iptables.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python3
+import argparse
+import configparser
+
+import iptc
+
+
+def _get_in_out_chains():
+ '''Return the inbound and outbound rule chains'''
+ table = iptc.Table(iptc.Table.NAT)
+ table.autocommit = False
+ return iptc.Chain(table, 'PREROUTING'), iptc.Chain(table, 'POSTROUTING')
+
+
+def inbound_rules(chain):
+ for rule in chain.rules:
+ if rule.target.name == 'DNAT':
+ public, _ = rule.dst.split('/')
+ private = rule.target.get_all_parameters()['to-destination'][0]
+ yield rule, public, private
+
+
+def outbound_rules(chain):
+ for rule in chain.rules:
+ if rule.target.name == 'SNAT':
+ private, _ = rule.src.split('/')
+ public = rule.target.get_all_parameters()['to-source'][0]
+ yield rule, public, private
+
+
+def _ls(args):
+ inchain, outchain = _get_in_out_chains()
+ inbound = [(pub, priv) for rule, pub, priv in inbound_rules(inchain)]
+ outbound = [(pub, priv) for rule, pub, priv in outbound_rules(outchain)]
+
+ if inbound != outbound:
+ print('ERROR: Mismatch between inbound and outbound rules!')
+
+ print('= Inbound public->private:')
+ for public, private in inbound:
+ print('%s -> %s' % (public, private))
+
+ print('\n= Outbound private->public:')
+ for public, private in outbound:
+ print('%s -> %s' % (private, public))
+
+
+def _sync_inbound(chain, pub_to_priv):
+ found = []
+ for rule, public, private in inbound_rules(chain):
+ mapping = (public, private)
+ if mapping in pub_to_priv:
+ found.append(mapping)
+ else:
+ print('Removing inbound mapping: %s->%s' % mapping)
+ chain.delete_rule(rule)
+ for public, private in pub_to_priv - set(found):
+ print('Adding inbound mapping: %s->%s' % (public, private))
+ rule = iptc.Rule()
+ rule.dst = '%s/255.255.255.255' % public
+ rule.protocol = 'ip'
+ t = rule.create_target('DNAT')
+ t.set_parameter('to-destination', [private])
+ chain.insert_rule(rule)
+
+
+def _sync_outbound(chain, pub_to_priv):
+ found = []
+ for rule, public, private in outbound_rules(chain):
+ mapping = (public, private)
+ if mapping in pub_to_priv:
+ found.append(mapping)
+ else:
+ print('Removing outbound mapping: %s->%s' % mapping)
+ chain.delete_rule(rule)
+ for public, private in pub_to_priv - set(found):
+ print('Adding outbound mapping: %s->%s' % (public, private))
+ rule = iptc.Rule()
+ rule.src = '%s/255.255.255.255' % private
+ rule.protocol = 'ip'
+ t = rule.create_target('SNAT')
+ t.set_parameter('to-source', [public])
+ chain.insert_rule(rule)
+
+
+def _sync(args):
+ cp = configparser.ConfigParser()
+ cp.read(args.file)
+ config = cp['public/private mappings']
+ pub_to_priv = set(config.items())
+
+ inchain, outchain = _get_in_out_chains()
+ _sync_inbound(inchain, pub_to_priv)
+ _sync_outbound(outchain, pub_to_priv)
+
+ if not args.dryrun:
+ inchain.table.commit()
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(
+ description='Manage public/private IP address mappings')
+ sub = parser.add_subparsers(title='Commands', metavar='')
+
+ p = sub.add_parser('ls', help='list mappgings')
+ p.set_defaults(func=_ls)
+
+ p = sub.add_parser('sync', help='sync rules defined in mapping file')
+ p.add_argument('--dryrun', action='store_true')
+ p.add_argument('--file', '-f', default='/etc/iptables.conf',
+ help='IP configuration mappings. default=%(default)s')
+ p.set_defaults(func=_sync)
+
+ args = parser.parse_args()
+ if getattr(args, 'func', None):
+ args.func(args)
diff --git a/roles/colo-router/handlers/main.yml b/roles/colo-router/handlers/main.yml
index 892aff61..20cef224 100644
--- a/roles/colo-router/handlers/main.yml
+++ b/roles/colo-router/handlers/main.yml
@@ -6,3 +6,6 @@
- name: reload squid
shell: /etc/init.d/squid3 reload
+
+- name: reload iptables
+ shell: /usr/local/bin/manage_iptables.py sync
diff --git a/roles/colo-router/tasks/main.yml b/roles/colo-router/tasks/main.yml
index 98c4f0b2..bc0ffa5c 100644
--- a/roles/colo-router/tasks/main.yml
+++ b/roles/colo-router/tasks/main.yml
@@ -65,12 +65,24 @@
regexp="^\/etc\/rc.aus-colo-nat #ADDED BY ANSIBLE"
insertbefore="exit 0"'
+- name: Copy manage_iptables.py
+ copy: src=manage_iptables.py dest=/usr/local/bin/manage_iptables.py mode=0655
+
+- name: Copy iptables.conf
+ copy: src=iptables.conf dest=/etc/iptables.conf mode=0655
+ tags:
+ - dns
+ notify:
+ - reload iptables
+
- name: Set up network interfaces
copy: src=router-interfaces
dest=/etc/network/interfaces
owner=root
group=root
mode=0644
+ tags:
+ - dns
- name: Set up hosts file
template: src=hosts.j2
@@ -79,7 +91,7 @@
group=root
mode=0644
tags:
- - dnsmasq
+ - dns
- name: Install dnsmasq
action: apt pkg=dnsmasq
@@ -93,7 +105,7 @@
notify:
- reload dnsmasq
tags:
- - dnsmasq
+ - dns
- name: Install pdu_power script
action: copy src=pdu_power