updown.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #!/usr/bin/env python
  2. import vici
  3. import daemon
  4. import logging
  5. from logging.handlers import SysLogHandler
  6. import subprocess
  7. logger = logging.getLogger('updownLogger')
  8. handler = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_DAEMON)
  9. handler.setFormatter(logging.Formatter('charon-updown: %(message)s'))
  10. logger.addHandler(handler)
  11. logger.setLevel(logging.INFO)
  12. def handle_interfaces(ike_sa, up):
  13. if_id_in = int(ike_sa['if-id-in'], 16)
  14. if_id_out = int(ike_sa['if-id-out'], 16)
  15. ifname_in = "xfrm-{}-in".format(if_id_in)
  16. ifname_out = "xfrm-{}-out".format(if_id_out)
  17. if up:
  18. logger.info("add XFRM interfaces %s and %s", ifname_in, ifname_out)
  19. subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_out,
  20. "-i", str(if_id_out), "-d", "eth0"])
  21. subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_in,
  22. "-i", str(if_id_in), "-d", "eth0"])
  23. subprocess.call(["ip", "link", "set", ifname_out, "up"])
  24. subprocess.call(["ip", "link", "set", ifname_in, "up"])
  25. subprocess.call(["iptables", "-A", "FORWARD", "-o", ifname_out,
  26. "-j", "ACCEPT"])
  27. subprocess.call(["iptables", "-A", "FORWARD", "-i", ifname_in,
  28. "-j", "ACCEPT"])
  29. else:
  30. logger.info("delete XFRM interfaces %s and %s", ifname_in, ifname_out)
  31. subprocess.call(["iptables", "-D", "FORWARD", "-o", ifname_out,
  32. "-j", "ACCEPT"])
  33. subprocess.call(["iptables", "-D", "FORWARD", "-i", ifname_in,
  34. "-j", "ACCEPT"])
  35. subprocess.call(["ip", "link", "del", ifname_out])
  36. subprocess.call(["ip", "link", "del", ifname_in])
  37. def install_routes(ike_sa):
  38. if_id_out = int(ike_sa['if-id-out'], 16)
  39. ifname_out = "xfrm-{}-out".format(if_id_out)
  40. child_sa = next(ike_sa["child-sas"].itervalues())
  41. for ts in child_sa['remote-ts']:
  42. logger.info("add route to %s via %s", ts, ifname_out)
  43. subprocess.call(["ip", "route", "add", ts, "dev", ifname_out])
  44. # daemonize and run parallel to the IKE daemon
  45. with daemon.DaemonContext():
  46. logger.debug("starting Python updown listener")
  47. try:
  48. session = vici.Session()
  49. ver = session.version()
  50. logger.info("connected to {daemon} {version} ({sysname}, {release}, "
  51. "{machine})".format(**ver))
  52. except:
  53. logger.error("failed to get status via vici")
  54. sys.exit(1)
  55. try:
  56. for label, event in session.listen(["ike-updown", "child-updown"]):
  57. logger.debug("received event: %s %s", label, repr(event))
  58. name = next((x for x in iter(event) if x != "up"))
  59. up = event.get("up", "") == "yes"
  60. ike_sa = event[name]
  61. if label == "ike-updown":
  62. handle_interfaces(ike_sa, up)
  63. elif label == "child-updown" and up:
  64. install_routes(ike_sa)
  65. except IOError:
  66. logger.error("daemon disconnected")
  67. except:
  68. logger.error("exception while listening for events " +
  69. repr(sys.exc_info()[1]))