Class: Shutter::Firewall::IPTables

Inherits:
Object
  • Object
show all
Defined in:
lib/shutter/iptables.rb

Constant Summary collapse

RULES_DMZ_BLOCK =
"# [RULES:DMZ]"
RULES_FORWARD_BLOCK =
"# [RULES:FORWARD]"
RULES_POSTROUTING_BLOCK =
"# [RULES:POSTROUTING]"
RULES_BASTARDS_BLOCK =
"# [RULES:BASTARDS]"
RULES_PUBLIC_BLOCK =
"# [RULES:PUBLIC]"
RULES_ALLOWIP_BLOCK =
"# [RULES:ALLOWIP]"
RULES_PRIVATE_BLOCK =
"# [RULES:PRIVATE]"
RULES_FAIL2BAN_BLOCK =
"# [RULES:FAIL2BAN]"
RULES_JAIL_BLOCK =
"# [RULES:JAIL]"
CHAIN_FAIL2BAN_BLOCK =
"# [CHAIN:FAIL2BAN]"

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ IPTables



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/shutter/iptables.rb', line 15

def initialize(path)
  @path = path
  @base = read("base.ipt",false).join("\n")
  @iface_forward = read("iface.forward")
  @ports_private = read("ports.private")
  @ports_public = read("ports.public")
  @ip_allow = read("ip.allow")
  @ip_deny = read("ip.deny")
  @dmz_device = read("iface.dmz")
  @os = Shutter::OS.new
end

Instance Method Details

#allow_ip_blockObject



154
155
156
157
158
159
160
161
# File 'lib/shutter/iptables.rb', line 154

def allow_ip_block
  content = ""
  @ip_allow.each do |line|
    raise "Invalid IP address in ip.allow" unless line =~ /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(\/[0-9]{0,2})*$/
    content += self.allow_ip_content(line)
  end
  content
end

#allow_ip_content(ip) ⇒ Object



216
217
218
# File 'lib/shutter/iptables.rb', line 216

def allow_ip_content(ip)
  "-A AllowIP -m state --state NEW -s #{ip} -j Allowed\n"
end

#allow_private_port_blockObject



134
135
136
137
138
139
140
141
# File 'lib/shutter/iptables.rb', line 134

def allow_private_port_block
  content = ""
  @ports_private.each do |line|
    port,proto = line.split
    content += self.allow_private_port_content(port, proto)
  end
  content
end

#allow_private_port_content(port, proto) ⇒ Object



208
209
210
# File 'lib/shutter/iptables.rb', line 208

def allow_private_port_content(port, proto)
  "-A Private -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j RETURN\n"
end

#allow_public_port_blockObject



143
144
145
146
147
148
149
150
151
152
# File 'lib/shutter/iptables.rb', line 143

def allow_public_port_block
  content = ""
  @ports_public.each do |line|
    port,proto = line.split
    raise "Invalid port in port.allow" unless port =~ /^[0-9].*$/
    raise "Invalid protocol in port.allow" unless proto =~ /^(tcp|udp)$/
    content += self.allow_public_port_content(port, proto)
  end
  content
end

#allow_public_port_content(port, proto) ⇒ Object



212
213
214
# File 'lib/shutter/iptables.rb', line 212

def allow_public_port_content(port, proto)
  "-A Public -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j ACCEPT\n"
end

#base_sub(block, content) ⇒ Object



27
28
29
# File 'lib/shutter/iptables.rb', line 27

def base_sub(block,content)
  @base = @base.gsub(/#{Regexp.quote(block)}/, content)
end

#checkObject

Check to see if base and iptables-save content match



104
105
106
107
108
109
# File 'lib/shutter/iptables.rb', line 104

def check
  gen_rules = filter_and_sort(generate)
  ips_rules = filter_and_sort(iptables_save)
  extra_rules = ips_rules - gen_rules
  extra_rules.empty?
end

#cleanObject



49
50
51
52
53
54
# File 'lib/shutter/iptables.rb', line 49

def clean
  @base = @base.gsub(/^#.*$/, "")
  @base = @base.gsub(/^$\n/, "")
  # Add a newline at the end
  @base + "\n"
end

#deny_ip_blockObject



163
164
165
166
167
168
169
170
# File 'lib/shutter/iptables.rb', line 163

def deny_ip_block
  content = ""
  @ip_deny.each do |line|
    raise "Invalid IP address in ip.deny" unless line =~ /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(\/[0-9]{0,2})*$/
    content += self.deny_ip_content(line)
  end
  content
end

#deny_ip_content(ip) ⇒ Object



220
221
222
# File 'lib/shutter/iptables.rb', line 220

def deny_ip_content(ip)
  "-A Bastards -s #{ip} -j DropBastards\n"
end

#dmz_device_blockObject



172
173
174
175
176
177
178
179
# File 'lib/shutter/iptables.rb', line 172

def dmz_device_block
  content = ""
  @dmz_device.each do |line|
    raise "Invalid device in iface.dmz" unless line =~ /^[a-z][a-z0-9].*$/
    content += self.dmz_device_content(line)
  end
  content
end

#dmz_device_content(iface) ⇒ Object



224
225
226
# File 'lib/shutter/iptables.rb', line 224

def dmz_device_content(iface)
  "-A Dmz -i #{iface} -j ACCEPT\n"
end

#fail2ban_chains_blockObject



181
182
183
# File 'lib/shutter/iptables.rb', line 181

def fail2ban_chains_block
  iptables_save.scan(/^:fail2ban.*$/).join("\n")
end

#fail2ban_rules_blockObject



185
186
187
# File 'lib/shutter/iptables.rb', line 185

def fail2ban_rules_block
  iptables_save.scan(/^-A fail2ban.*$/).join("\n")
end

#forward_blockObject

Block Generation



114
115
116
117
118
119
120
121
# File 'lib/shutter/iptables.rb', line 114

def forward_block
  content = ""
  @iface_forward.each do |line|
    src, dst = line.split(' ')
    content += self.forward_content(src,dst)
  end
  content
end

#forward_content(src, dst) ⇒ Object

Block Content



198
199
200
201
202
# File 'lib/shutter/iptables.rb', line 198

def forward_content(src,dst)
  rule =  "-A FORWARD -i #{src} -o #{dst} -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT\n"
  rule += "-A FORWARD -i #{dst} -o #{src} -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
  rule
end

#generateObject



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/shutter/iptables.rb', line 31

def generate
  base_sub(RULES_DMZ_BLOCK,          dmz_device_block)
  base_sub(RULES_FORWARD_BLOCK,      forward_block)
  base_sub(RULES_POSTROUTING_BLOCK,  postrouting_block)
  base_sub(RULES_BASTARDS_BLOCK,     deny_ip_block)
  base_sub(RULES_PUBLIC_BLOCK,       allow_public_port_block)
  base_sub(RULES_ALLOWIP_BLOCK,      allow_ip_block)
  base_sub(RULES_PRIVATE_BLOCK,      allow_private_port_block)
  base_sub(RULES_FAIL2BAN_BLOCK,     fail2ban_rules_block)
  base_sub(RULES_JAIL_BLOCK,         jail_rules_block)
  base_sub(CHAIN_FAIL2BAN_BLOCK,     fail2ban_chains_block)
  clean
end

#iptables_restoreObject



97
98
99
# File 'lib/shutter/iptables.rb', line 97

def iptables_restore
  "#{@os.iptables_restore}"
end

#iptables_saveObject

IPTables Commands



93
94
95
# File 'lib/shutter/iptables.rb', line 93

def iptables_save
  @iptable_save ||= `"#{@os.iptables_save}"`
end

#jail_rules_blockObject



189
190
191
192
193
# File 'lib/shutter/iptables.rb', line 189

def jail_rules_block
  lines = iptables_save.scan(/^-A Jail.*$/)
  lines << "-A Jail -j RETURN\n" unless lines.last =~ /-A Jail -j RETURN/
  lines.join("\n")
end

#persist(pfile) ⇒ Object



84
85
86
87
88
# File 'lib/shutter/iptables.rb', line 84

def persist(pfile)
  File.open(pfile, "w") do |f|
    f.write(@base)
  end
end

#postrouting_blockObject



123
124
125
126
127
128
129
130
131
132
# File 'lib/shutter/iptables.rb', line 123

def postrouting_block
  masq_ifaces = []
  content = ""
  @iface_forward.each do |line|
    src, dst = line.split(' ')
    content += self.postrouting_content(dst) unless masq_ifaces.include?(dst)
    masq_ifaces << dst
  end
  content
end

#postrouting_content(iface) ⇒ Object



204
205
206
# File 'lib/shutter/iptables.rb', line 204

def postrouting_content(iface)
  "-A POSTROUTING -o #{iface} -j MASQUERADE\n"
end

#read(file, filter = true) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/shutter/iptables.rb', line 56

def read(file, filter=true)
  #puts "Reading: #{@path}/#{file}"
  lines = File.read("#{@path}/#{file}").split("\n")
  # Doesn't work with 1.8.x
  # lines.keep_if{ |line| line =~ /^[a-z0-9].+$/ } if filter
  # so since we are iterating through this, well handle the stripping as well
  # lines.map { |line| line.strip }
  newlines = []
  lines.each do |line|
    if filter
      newlines << line.strip if line =~ /^[a-z0-9].+$/
    else
      newlines << line.strip
    end
  end
  newlines
end

#restoreObject



78
79
80
81
82
# File 'lib/shutter/iptables.rb', line 78

def restore
  IO.popen("#{iptables_restore}", "r+") do |iptr|
    iptr.puts self.generate ; iptr.close_write
  end
end

#saveObject



74
75
76
# File 'lib/shutter/iptables.rb', line 74

def save
  puts self.generate
end

#to_sObject



45
46
47
# File 'lib/shutter/iptables.rb', line 45

def to_s
  @base
end