Skip to content

Instantly share code, notes, and snippets.

@mhahl
Last active August 29, 2015 14:05
Show Gist options
  • Save mhahl/07ed57e56cfb801af93f to your computer and use it in GitHub Desktop.
Save mhahl/07ed57e56cfb801af93f to your computer and use it in GitHub Desktop.
#!/bin/ruby
######################################################
#
# Author: Mark Hahl
# Email: mark@deviateit.net
# Version: 0.0.0
#
# Firewall configuration script for gateway server,
# managing traffic and other rules.
#
#####################################################
require 'yaml'
puts "#"
puts "# Firewall Script Generated at #{Time.now}"
puts "# Do not edit this script directly."
puts "#"
# Interfaces the server will use
# there could be more than this
# when we get the new device
#
INT = "eth1"
EXT = "eth0"
IPT = "iptables"
ARP = "arptables"
SAR = "arp"
GW = "10.0.0.1"
# Quota limits (In Bytes).
# - Q_ON: Quota for onpeak hours
# - Q_OFF: Quota for off peak hours.
#
Q_ON = 125000000000
Q_OFF = 125000000000
# Time frame for quota counting depending
# on time frame.
# - TIME_START: Start of onpeak hours
# begining of off peak hours.
# - TIME_STOP: Stop of onpeak hours
# begining of off peak hours
#
TIME_START = "07:00"
TIME_STOP = "19:00"
# Internode UNMERTERED content list of IP addresses.
# this should be the file AS IS from the URL:
#
# https://customer-webtools-api.internode.on.net/unmetered_ip_address_list.txt
#
UNMETERED_CONTENT = File.read("conf/unmetered_ip_address_list.txt")
# Users and there IP Addresses and
# mac addresses associated with them
# associated with the user.The output from
# the file should look like the hashmap below:
#
# USERS = {
# :MARK => {
# "10.0.0.20" => "00:b5:6d:00:f9:50",
# "10.0.0.21" => "00:b5:6d:00:f9:51",
# "10.0.0.22" => "00:b5:6d:00:f9:52",
# },
# :JACK => {
# "10.0.0.10" => "74:D0:2B:CB:80:CB"
# }
# }
#
USERS = YAML::load(File.read("conf/clients.yaml"))
# Flush all the rules.
#
puts "#{IPT} -F"
# Delete tables for QUOTAS if they already exist.
# this stops the script from complaining.
#
USERS.each do |user, ips|
puts "#{IPT} -X #{user}_QUOTA"
end
# Default policies for
# the firewall is to drop everything
# unless there is a rule allowing.
#
puts "#{IPT} -P INPUT DROP"
puts "#{IPT} -P FORWARD DROP"
puts "#{IPT} -P OUTPUT ACCEPT"
# Enable NAT or something
# similar.
#
puts "#{IPT} -t nat -A POSTROUTING -o #{EXT} -j MASQUERADE"
# Set all UDP trafic to minimal-delay.
#
puts "#{IPT} -t mangle -A PREROUTING -p udp -j TOS --set-tos 0x04"
# Drop invalid packets straigt away.
#
puts "#{IPT} -A INPUT -m state --state INVALID -j DROP"
puts "#{IPT} -A FORWARD -m state --state INVALID -j DROP"
puts "#{IPT} -A OUTPUT -m state --state INVALID -j DROP"
# Accept ICMP and all traffic from loopback.
#
puts "#{IPT} -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT"
puts "#{IPT} -A INPUT -i lo -j ACCEPT"
puts "#{IPT} -A INPUT -p icmp -j ACCEPT"
puts "#{IPT} -A INPUT -i eth1 -j ACCEPT"
puts "#{IPT} -A OUTPUT -o eth1 -j ACCEPT"
# Drop bogus TCP packets
#
puts "#{IPT} -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP"
puts "#{IPT} -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP"
# Open ports for services.
# - 22: SSH Server
# - 67: DHCP
# - 68: DHCP
# - 53: DNS
#
puts "#{IPT} -A INPUT -p tcp --dport 22 -j ACCEPT"
puts "#{IPT} -A INPUT -p tcp --dport 67 -j ACCEPT"
puts "#{IPT} -A INPUT -p tcp --dport 68 -j ACCEPT"
puts "#{IPT} -A INPUT -p tcp --dport 53 -j ACCEPT"
puts "#{IPT} -A INPUT -j DROP"
# Forward and accept all packets to the Internode Unmetered IPS
# These will not get forwared to the quota chain and wont be
# counted.
#
UNMETERED_CONTENT.split("\n\n")[0].each_line do |ip|
puts "#{IPT} -A FORWARD -s #{ip.strip()} -j ACCEPT"
puts "#{IPT} -A FORWARD -d #{ip.strip()} -j ACCEPT"
end
# Create the monitoring table for each user
# This will count and block the user when the quota reaches the limit.
#
USERS.each do |user, ips|
puts "#{IPT} -N #{user}_QUOTA"
puts "#{IPT} -A #{user}_QUOTA -m quota --quota #{Q_ON} -m time --timestart #{TIME_STOP} --timestop #{TIME_START} -j ACCEPT"
puts "#{IPT} -A #{user}_QUOTA -m quota --quota #{Q_OFF} -m time --timestart #{TIME_START} --timestop #{TIME_STOP} -j ACCEPT"
end
# When a packet is received, forwared it on to the
# quota chain.
#
USERS.each do |user, hosts|
hosts.each do |ip, mac|
puts "#{IPT} -A FORWARD -d #{ip} -j #{user}_QUOTA"
puts "#{IPT} -A FORWARD -s #{ip} -j #{user}_QUOTA"
end
end
# Drop everything that doesn't match the above rules.
#
puts "#{IPT} -A FORWARD -j REJECT --reject-with icmp-admin-prohibited"
# Flush the arptables rules
# set default policy to drop everything.
#
puts "#{ARP} -F"
puts "#{ARP} -P IN DROP"
puts "#{ARP} -P OUT ACCEPT"
puts "#{ARP} -P FORWARD ACCEPT"
# Set up arp tables to do the policy enforcments.
# Do not accept trafic from the client if the IP and mac
# are not the same as in the table.
#
# - Allow clients which match the table.
# - Allow all traffic comming from the external interface.
#
USERS.each do |user, hosts|
hosts.each do |ip, mac|
puts "#{ARP} -A IN -i #{INT} -d #{GW} -z #{mac} -j ACCEPT"
puts "#{ARP} -A IN -i #{INT} -s #{ip} -z #{mac} -j ACCEPT"
end
end
# Accept everything coming from the external
# interface.
#
puts "#{ARP} -A IN -i #{EXT} -j ACCEPT"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment