SHARE
TWEET

server_iptables.py

jcomeau_ictx Feb 10th, 2014 115 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python -OO
  2. '''
  3. set up iptables for typical server
  4.  
  5. make sure to edit /etc/services accordingly
  6. '''
  7. import sys, os, socket
  8. from subprocess import Popen, PIPE
  9. TCP_SERVICES = ['ssh', 'smtp', 'http', 'https', 'rootssh',
  10.  'lighttpd']
  11. UDP_SERVICES = ['domain', 'bootps', 'resolver', 'ntp']
  12. CRYPTO_COINS = ['americancoin', 'coinyecoin', 'bitcoin', 'dogecoin',
  13.  'betacoin', 'ppcoin', 'freicoin', 'nexuscoin']
  14. TCP_CLIENTS = ['ssh', 'http', 'https', 'whois', 'ircd'] + CRYPTO_COINS
  15. UDP_CLIENTS = ['domain', 'bootps', 'resolver', 'ntp', 'skype']
  16. ACCEPT_ALL_LOCAL = True  # if False, must enable cryptocoin RPC
  17. # be sure to also add _rpc entries for each, e.g. bitcoin_rpc in /etc/services
  18. def check_service(service_name):
  19.  try:
  20.   return socket.getservbyname(service_name)
  21.  except:
  22.   raise Exception('no such service "%s"' % service_name)
  23. def iptables(args):
  24.  command = ['iptables'] + args
  25.  pipeline = Popen(command, stdout = PIPE, stderr = PIPE)
  26.  result = pipeline.wait()
  27.  if result:
  28.   raise Exception('"%s" error: "%s"' % (' '.join(command),
  29.    pipeline.stderr.readlines()[-1].rstrip()))
  30. def accept_all_local():
  31.  iptables(['--append', 'INPUT', '--in-interface', 'lo', '--jump', 'ACCEPT'])
  32.  iptables(['--append', 'OUTPUT', '--out-interface', 'lo', '--jump', 'ACCEPT'])
  33. def accept_local_input(port, protocol = 'tcp'):
  34.  iptables(['--append', 'INPUT', '--in-interface', 'lo', '--protocol', protocol,
  35.   '--destination-port', port, '--jump', 'ACCEPT'])
  36. def accept_local_output(port, protocol = 'tcp'):
  37.  iptables(['--append', 'OUTPUT', '--out-interface', 'lo',
  38.   '--protocol', protocol, '--source-port', port, '--jump', 'ACCEPT'])
  39. def accept_local(port, protocol = 'tcp'):
  40.  accept_local_input(port, protocol)
  41.  accept_local_output(port, protocol)
  42. def accept_server_input(port, protocol = 'tcp'):
  43.  iptables(['--append', 'INPUT', '--protocol', protocol,
  44.   '--destination-port', port, '--jump', 'ACCEPT'])
  45. def accept_server_output(port, protocol = 'tcp'):
  46.  iptables(['--append', 'OUTPUT', '--protocol', protocol,
  47.   '--source-port', port, '--jump', 'ACCEPT'])
  48. def accept_client_input(port, protocol = 'tcp'):
  49.  iptables(['--append', 'INPUT', '--protocol', protocol,
  50.   '--source-port', port, '--jump', 'ACCEPT'])
  51. def accept_client_output(port, protocol = 'tcp'):
  52.  iptables(['--append', 'OUTPUT', '--protocol', protocol,
  53.   '--destination-port', port, '--jump', 'ACCEPT'])
  54. def accept_server_traffic(port, protocol = 'tcp'):
  55.  accept_server_input(port, protocol)
  56.  accept_server_output(port, protocol)
  57. def accept_client_traffic(port, protocol = 'tcp'):
  58.  accept_client_input(port, protocol)
  59.  accept_client_output(port, protocol)
  60. def init():
  61.  for service in TCP_SERVICES + CRYPTO_COINS:
  62.   check_service(service)
  63.  for service in CRYPTO_COINS:
  64.   service += '_rpc'
  65.   check_service(service)
  66.  init_firewall()
  67. def init_firewall():
  68.  'start from a clean but paranoid slate, dropping everything on the floor'
  69.  flush_firewall()
  70.  for chain in ['INPUT', 'OUTPUT', 'FORWARD']:
  71.   iptables(['--policy', chain, 'DROP'])
  72. def flush_firewall():
  73.  'flush built-in chains, delete non-builtins, and zero counters'
  74.  for initializer in ['--flush', '--delete-chain', '--zero']:
  75.   iptables([initializer])
  76. def reset_firewall():
  77.  'start from a clean slate, allowing all traffic'
  78.  flush_firewall
  79.  for chain in ['INPUT', 'OUTPUT', 'FORWARD']:
  80.   iptables(['--policy', chain, 'ACCEPT'])
  81. def firewall(*args):
  82.  '''
  83. set up firewall
  84.  
  85. if anything breaks, undo firewall so we aren't locked out
  86. '''
  87.  if os.geteuid() > 0:
  88.   print >>sys.stderr, 'Must be root (sudo may work)'
  89.   sys.exit(1)
  90.  if __debug__:
  91.   bad_command()
  92.  try:
  93.   init()
  94.   enable_some_inputs()
  95.   enable_some_outputs()
  96.   for service in TCP_SERVICES + CRYPTO_COINS:
  97.    accept_server_traffic(service)
  98.   for service in UDP_SERVICES:
  99.    accept_server_traffic(service, protocol = 'udp')
  100.   for client in TCP_CLIENTS:
  101.    accept_client_traffic(client)
  102.   for client in UDP_CLIENTS:
  103.    accept_client_traffic(client, protocol = 'udp')
  104.   if ACCEPT_ALL_LOCAL:
  105.    accept_all_local()
  106.   else:
  107.    for service in CRYPTO_COINS:
  108.     service += '_rpc'
  109.     accept_local(service)
  110.   block_unwanted_inputs()
  111.   block_unwanted_outputs()
  112.  except Exception, error:
  113.   reset_firewall()
  114.   raise error
  115. def bad_command():
  116.  'something that iptables will reject, as a test'
  117.  iptables(['not', 'understood'])
  118. def block_unwanted_inputs():
  119.  '''
  120. log and reject connection attempts and other questionable packets
  121.  
  122. null packets, pingflood, christmastree
  123. '''
  124.  iptables(['--append', 'INPUT', '--match', 'state', '!', '--state', 'NEW',
  125.   '--jump', 'LOG', '--log-prefix', 'unmatched INPUT '])
  126.  iptables(['--append', 'INPUT', '--match', 'state', '!', '--state', 'NEW',
  127.   '--jump', 'REJECT'])
  128.  iptables(['--append', 'INPUT', '--protocol', 'tcp', '--tcp-flags', 'ALL',
  129.   'NONE', '--jump', 'DROP'])  # null packets
  130.  iptables(['--append', 'INPUT', '--protocol', 'tcp', '--tcp-flags', 'ALL',
  131.   'ALL', '--jump', 'DROP'])  # christmastree
  132.  iptables(['--append', 'INPUT', '--protocol', 'tcp', '!', '--syn', '--match',
  133.   'state', '--state', 'NEW', '--jump', 'DROP'])  # pingflood
  134. def enable_some_inputs():
  135.  'allow established and other selected inputs'
  136.  iptables(['--append', 'INPUT', '--match', 'state', '--state',
  137.   'ESTABLISHED,RELATED', '--jump', 'ACCEPT'])
  138.  iptables(['--append', 'INPUT', '--protocol', 'icmp', '--match', 'icmp',
  139.   '--icmp-type', '8', '--jump', 'ACCEPT'])  # ping
  140. def enable_some_outputs():
  141.  iptables(['--append', 'OUTPUT', '--protocol', 'icmp', '--match', 'icmp',
  142.   '--icmp-type', '8', '--jump', 'ACCEPT'])  # ping requests
  143.  iptables(['--append', 'OUTPUT', '--protocol', 'icmp', '--match', 'icmp',
  144.   '--icmp-type', '3', '--jump', 'ACCEPT'])  # report errors
  145. def block_unwanted_outputs():
  146.  iptables(['--append', 'OUTPUT', '--jump', 'LOG',
  147.   '--log-prefix', 'unmatched OUTPUT '])
  148.  iptables(['--append', 'OUTPUT', '--jump', 'REJECT'])
  149.  iptables(['--append', 'FORWARD', '--jump', 'LOG',
  150.   '--log-prefix', 'unmatched FORWARD '])
  151.  iptables(['--append', 'FORWARD', '--jump', 'REJECT'])
  152. if __name__ == '__main__':
  153.  firewall(*sys.argv[1:])
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top