shutter 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/shutter.rb CHANGED
@@ -3,5 +3,12 @@ require "shutter/content"
3
3
  require "shutter/command_line"
4
4
 
5
5
  module Shutter
6
- # Your code goes here...
6
+ CONFIG_FILES = %w[
7
+ base.ipt
8
+ iface.dmz
9
+ ip.allow
10
+ ip.deny
11
+ ports.private
12
+ ports.public
13
+ ]
7
14
  end
@@ -1,71 +1,105 @@
1
1
  require 'optparse'
2
2
  require 'shutter/iptables'
3
+ require 'shutter/os'
3
4
 
4
5
  module Shutter
5
- class CommandLine
6
- def initialize( path = "/etc/shutter.d")
7
- @config_path = path
8
- # Make sure that we have the proper files
9
- files = %w[
10
- base.ipt
11
- iface.dmz
12
- ip.allow
13
- ip.deny
14
- ports.private
15
- ports.public
16
- ]
17
- files.each do |name|
18
- file = "#{@config_path}/#{name}"
19
- unless File.exists?(file)
20
- # puts "Creating: #{file}"
21
- File.open(file, 'w') do |f|
22
- f.write(Shutter.const_get(name.upcase.gsub(/\./, "_")))
23
- end
24
- end
25
- end
26
- end
6
+ class CommandLine
7
+ def initialize( path = "/etc/shutter.d")
8
+ # Currently only available to RedHat variants
9
+ @os = Shutter::OS.new
10
+ unless @os.redhat?
11
+ puts "Shutter is currently only compatible with RedHat and its variants."
12
+ puts "Help make it compatible with others (github.com/rlyon/shutter)"
13
+ exit
14
+ end
27
15
 
28
- def execute
29
- options = {}
30
- optparse = OptionParser.new do |opts|
31
- opts.banner = "Usage: shutter [options]"
32
- options[:command] = :save
33
- opts.on( '-s', '--save', 'Output the firewall to stdout.') do
34
- options[:command] = :save
35
- end
36
- opts.on( '-r', '--restore', 'Load the firewall through iptables-restore.') do
37
- options[:command] = :restore
38
- end
39
- options[:debug] = false
40
- opts.on( '-d', '--debug', 'Be a bit more chatty') do
41
- options[:debug] = true
42
- end
43
- opts.on_tail( '-h', '--help', 'Display this screen' ) do
44
- puts opts
45
- exit
46
- end
47
- opts.on_tail( '--version', "Show the version") do
48
- puts Shutter::VERSION
49
- exit
50
- end
51
- end
52
- optparse.parse!
53
- puts "* Using config path: #{@config_path}" if options[:debug]
54
- puts "* Running command: #{options[:command].to_s}" if options[:debug]
55
- send(options[:command])
56
- end
16
+ @config_path = path
17
+ @iptables = Shutter::IPTables::Base.new(@config_path)
18
+
19
+ end
57
20
 
58
- def save
59
- @ipt = Shutter::IPTables::Base.new(@config_path).generate
60
- puts @ipt
61
- end
21
+ def execute
22
+ options = {}
23
+ optparse = OptionParser.new do |opts|
24
+ opts.banner = "Usage: shutter [options]"
25
+ options[:command] = :save
26
+ opts.on( '--init', 'Create the initial configuration files' ) do
27
+ options[:command] = :init
28
+ end
29
+ opts.on( '--reinit', 'Rereate the initial configuration files' ) do
30
+ options[:command] = :reinit
31
+ end
32
+ opts.on( '-s', '--save', 'Output the firewall to stdout. (DEFAULT)') do
33
+ options[:command] = :save
34
+ end
35
+ opts.on( '-r', '--restore', 'Load the firewall through iptables-restore.') do
36
+ options[:command] = :restore
37
+ end
38
+ @persist = false
39
+ opts.on( '-p', '--persist', 'Make the changes persistant. (with --restore)') do
40
+ @persist = true
41
+ end
42
+ options[:debug] = false
43
+ opts.on( '-d', '--debug', 'Be a bit more chatty') do
44
+ options[:debug] = true
45
+ end
46
+ opts.on_tail( '-h', '--help', 'Display this screen' ) do
47
+ puts opts
48
+ exit
49
+ end
50
+ opts.on_tail( '--version', "Show the version") do
51
+ puts Shutter::VERSION
52
+ exit
53
+ end
54
+ end
55
+ optparse.parse!
56
+ puts "* Using config path: #{@config_path}" if @debug
57
+ puts "* Running command: #{options[:command].to_s}" if @debug
58
+ send(options[:command])
59
+ end
62
60
 
63
- def restore
64
- @ipt = Shutter::IPTables::Base.new(@config_path).generate
65
- IO.popen("#{Shutter::IPTables::IPTABLES_RESTORE}", "r+") do |iptr|
66
- iptr.puts @ipt ; iptr.close_write
67
- end
68
- end
61
+ def init
62
+ Shutter::CONFIG_FILES.each do |name|
63
+ file = "#{@config_path}/#{name}"
64
+ unless File.exists?(file)
65
+ # puts "Creating: #{file}"
66
+ File.open(file, 'w') do |f|
67
+ f.write(Shutter.const_get(name.upcase.gsub(/\./, "_")))
68
+ end
69
+ end
70
+ end
71
+ end
69
72
 
70
- end
73
+ def reinit
74
+ Shutter::CONFIG_FILES.each do |name|
75
+ file = "#{@config_path}/#{name}"
76
+ File.open(file, 'w') do |f|
77
+ f.write(Shutter.const_get(name.upcase.gsub(/\./, "_")))
78
+ end
79
+ end
80
+ end
81
+
82
+ def save
83
+ init
84
+ @ipt = @iptables.generate
85
+ puts @ipt
86
+ end
87
+
88
+ def restore
89
+ init
90
+ @ipt = @iptables.generate
91
+ IO.popen("#{Shutter::IPTables::IPTABLES_RESTORE}", "r+") do |iptr|
92
+ iptr.puts @ipt ; iptr.close_write
93
+ end
94
+ persist if @persist
95
+ end
96
+
97
+ def persist
98
+ pfile = ENV['SHUTTER_PERSIST_FILE'] ? ENV['SHUTTER_PERSIST_FILE'] : @iptables.persist_file(@os)
99
+ File.open(pfile, "w") do |f|
100
+ f.write(@ipt)
101
+ end
102
+ end
103
+
104
+ end
71
105
  end
@@ -167,12 +167,12 @@ IP_DENY = %q{# Generated by Shutter
167
167
 
168
168
  PORTS_PUBLIC = %q{
169
169
  # proto port
170
- # 80 tcp
171
- # 443 tcp
170
+ # 80 tcp
171
+ # 443 tcp
172
172
  }
173
173
 
174
174
  PORTS_PRIVATE = %q{
175
175
  # proto port
176
- 22 tcp
176
+ 22 tcp
177
177
  }
178
178
  end
@@ -3,9 +3,10 @@ require 'shutter/iptables/eyepee'
3
3
  require 'shutter/iptables/iface'
4
4
  require 'shutter/iptables/jail'
5
5
  require 'shutter/iptables/port'
6
+ require 'shutter/os'
6
7
 
7
8
  module Shutter
8
- module IPTables
9
- IPTABLES_RESTORE="/sbin/iptables-restore"
10
- end
9
+ module IPTables
10
+ IPTABLES_RESTORE="/sbin/iptables-restore"
11
+ end
11
12
  end
@@ -1,45 +1,49 @@
1
1
  module Shutter
2
- module IPTables
3
- class Base
4
- def initialize( path )
5
- @path = path
6
- file = File.open("#{path}/base.ipt", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class Base
4
+ def initialize( path )
5
+ @path = path
6
+ file = File.open("#{path}/base.ipt", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def persist_file(os)
11
+ "/etc/sysconfig/iptables"
12
+ end
13
13
 
14
- def generate
15
- #generate_nat
16
- generate_filter
17
- end
14
+ def to_s
15
+ @content
16
+ end
18
17
 
19
- def generate_filter
20
- @dmz = Iface.new("#{@path}", :dmz).to_ipt
21
- @content = @content.gsub(/#\ \[RULES:DMZ\]/, @dmz)
22
- @bastards = EyePee.new("#{@path}", :deny).to_ipt
23
- @content = @content.gsub(/#\ \[RULES:BASTARDS\]/, @bastards)
24
- @public = Port.new("#{@path}", :public).to_ipt
25
- @content = @content.gsub(/#\ \[RULES:PUBLIC\]/, @public)
26
- @allow = EyePee.new("#{@path}", :allow).to_ipt
27
- @content = @content.gsub(/#\ \[RULES:ALLOWIP\]/, @allow)
28
- @private = Port.new("#{@path}", :private).to_ipt
29
- @content = @content.gsub(/#\ \[RULES:PRIVATE\]/, @private)
18
+ def generate
19
+ #generate_nat
20
+ generate_filter
21
+ end
30
22
 
31
- # Make sure we are restoring what fail2ban has added
32
- @f2b_chains = Jail.new.fail2ban_chains
33
- @content = @content.gsub(/#\ \[CHAIN:FAIL2BAN\]/, @f2b_chains)
34
- @f2b_rules = Jail.new.fail2ban_rules
35
- @content = @content.gsub(/#\ \[RULES:FAIL2BAN\]/, @f2b_rules)
36
- @jail = Jail.new.jail_rules
37
- @content = @content.gsub(/#\ \[RULES:JAIL\]/, @jail)
23
+ def generate_filter
24
+ @dmz = Iface.new("#{@path}", :dmz).to_ipt
25
+ @content = @content.gsub(/#\ \[RULES:DMZ\]/, @dmz)
26
+ @bastards = EyePee.new("#{@path}", :deny).to_ipt
27
+ @content = @content.gsub(/#\ \[RULES:BASTARDS\]/, @bastards)
28
+ @public = Port.new("#{@path}", :public).to_ipt
29
+ @content = @content.gsub(/#\ \[RULES:PUBLIC\]/, @public)
30
+ @allow = EyePee.new("#{@path}", :allow).to_ipt
31
+ @content = @content.gsub(/#\ \[RULES:ALLOWIP\]/, @allow)
32
+ @private = Port.new("#{@path}", :private).to_ipt
33
+ @content = @content.gsub(/#\ \[RULES:PRIVATE\]/, @private)
38
34
 
39
- # Remove the rest of the comments and extra lines
40
- @content = @content.gsub(/^#.*$/, "")
41
- @content = @content.gsub(/^$\n/, "")
42
- end
43
- end
44
- end
35
+ # Make sure we are restoring what fail2ban has added
36
+ @f2b_chains = Jail.new.fail2ban_chains
37
+ @content = @content.gsub(/#\ \[CHAIN:FAIL2BAN\]/, @f2b_chains)
38
+ @f2b_rules = Jail.new.fail2ban_rules
39
+ @content = @content.gsub(/#\ \[RULES:FAIL2BAN\]/, @f2b_rules)
40
+ @jail = Jail.new.jail_rules
41
+ @content = @content.gsub(/#\ \[RULES:JAIL\]/, @jail)
42
+
43
+ # Remove the rest of the comments and extra lines
44
+ @content = @content.gsub(/^#.*$/, "")
45
+ @content = @content.gsub(/^$\n/, "")
46
+ end
47
+ end
48
+ end
45
49
  end
@@ -1,34 +1,34 @@
1
1
  module Shutter
2
- module IPTables
3
- class EyePee
4
- def initialize( path, state )
5
- @state = state
6
- file = File.open("#{path}/ip.#{state.to_s}", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class EyePee
4
+ def initialize( path, state )
5
+ @state = state
6
+ file = File.open("#{path}/ip.#{state.to_s}", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def to_s
11
+ @content
12
+ end
13
13
 
14
- def to_ipt
15
- @rules = ""
16
- @content.each_line do |ip|
17
- ip_clean = ip.strip
18
- if ip_clean =~ /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(\/[0-9]{0,2})*$/
19
- @rules += send(:"#{@state.to_s}_ipt", ip_clean)
20
- end
21
- end
22
- @rules
23
- end
14
+ def to_ipt
15
+ @rules = ""
16
+ @content.each_line do |ip|
17
+ ip_clean = ip.strip
18
+ if ip_clean =~ /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(\/[0-9]{0,2})*$/
19
+ @rules += send(:"#{@state.to_s}_ipt", ip_clean)
20
+ end
21
+ end
22
+ @rules
23
+ end
24
24
 
25
- def allow_ipt(ip)
26
- "-A AllowIP -m state --state NEW -s #{ip} -j Allowed\n"
27
- end
25
+ def allow_ipt(ip)
26
+ "-A AllowIP -m state --state NEW -s #{ip} -j Allowed\n"
27
+ end
28
28
 
29
- def deny_ipt(ip)
30
- "-A Bastards -s #{ip} -j DropBastards\n"
31
- end
32
- end
33
- end
29
+ def deny_ipt(ip)
30
+ "-A Bastards -s #{ip} -j DropBastards\n"
31
+ end
32
+ end
33
+ end
34
34
  end
@@ -1,30 +1,30 @@
1
1
  module Shutter
2
- module IPTables
3
- class Iface
4
- def initialize( path, type )
5
- @type = type
6
- file = File.open("#{path}/iface.#{type.to_s}", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class Iface
4
+ def initialize( path, type )
5
+ @type = type
6
+ file = File.open("#{path}/iface.#{type.to_s}", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def to_s
11
+ @content
12
+ end
13
13
 
14
- def to_ipt
15
- @rules = ""
16
- @content.each_line do |line|
17
- line = line.strip
18
- if line =~ /^[a-z].+$/
19
- @rules += send(:"#{@type.to_s}_ipt", line)
20
- end
21
- end
22
- @rules
23
- end
14
+ def to_ipt
15
+ @rules = ""
16
+ @content.each_line do |line|
17
+ line = line.strip
18
+ if line =~ /^[a-z].+$/
19
+ @rules += send(:"#{@type.to_s}_ipt", line)
20
+ end
21
+ end
22
+ @rules
23
+ end
24
24
 
25
- def dmz_ipt( iface )
26
- "-A Dmz -i #{iface} -j ACCEPT\n"
27
- end
28
- end
29
- end
25
+ def dmz_ipt( iface )
26
+ "-A Dmz -i #{iface} -j ACCEPT\n"
27
+ end
28
+ end
29
+ end
30
30
  end
@@ -1,26 +1,26 @@
1
1
  module Shutter
2
- module IPTables
3
- class Jail
4
- def initialize( iptables = "/sbin/iptables")
5
- @iptables = iptables
6
- end
2
+ module IPTables
3
+ class Jail
4
+ def initialize( iptables = "/sbin/iptables")
5
+ @iptables = iptables
6
+ end
7
7
 
8
- def fail2ban_chains
9
- `/sbin/iptables-save | grep "^:fail2ban"`
10
- end
8
+ def fail2ban_chains
9
+ `/sbin/iptables-save | grep "^:fail2ban"`
10
+ end
11
11
 
12
- def fail2ban_rules
13
- `/sbin/iptables-save | grep "^-A fail2ban"`
14
- end
12
+ def fail2ban_rules
13
+ `/sbin/iptables-save | grep "^-A fail2ban"`
14
+ end
15
15
 
16
- def jail_rules
17
- jail = `/sbin/iptables-save | grep "^-A Jail"`
18
- lines = jail.split('\n')
19
- unless lines != [] && lines[-1] == "-A Jail -j RETURN\n"
20
- jail += "-A Jail -j RETURN\n"
21
- end
22
- jail
23
- end
24
- end
25
- end
16
+ def jail_rules
17
+ jail = `/sbin/iptables-save | grep "^-A Jail"`
18
+ lines = jail.split('\n')
19
+ unless lines != [] && lines[-1] == "-A Jail -j RETURN\n"
20
+ jail += "-A Jail -j RETURN\n"
21
+ end
22
+ jail
23
+ end
24
+ end
25
+ end
26
26
  end
@@ -1,35 +1,35 @@
1
1
  module Shutter
2
- module IPTables
3
- class Port
4
- def initialize( path, type )
5
- @type = type
6
- file = File.open("#{path}/ports.#{type.to_s}", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class Port
4
+ def initialize( path, type )
5
+ @type = type
6
+ file = File.open("#{path}/ports.#{type.to_s}", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def to_s
11
+ @content
12
+ end
13
13
 
14
- def to_ipt
15
- @rules = ""
16
- @content.each_line do |line|
17
- line = line.strip
18
- if line =~ /^[1-9].+$/
19
- port,proto = line.split
20
- @rules += send(:"#{@type.to_s}_ipt", port, proto)
21
- end
22
- end
23
- @rules
24
- end
14
+ def to_ipt
15
+ @rules = ""
16
+ @content.each_line do |line|
17
+ line = line.strip
18
+ if line =~ /^[1-9].+$/
19
+ port,proto = line.split
20
+ @rules += send(:"#{@type.to_s}_ipt", port, proto)
21
+ end
22
+ end
23
+ @rules
24
+ end
25
25
 
26
- def private_ipt( port, proto )
27
- "-A Private -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j RETURN\n"
28
- end
26
+ def private_ipt( port, proto )
27
+ "-A Private -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j RETURN\n"
28
+ end
29
29
 
30
- def public_ipt( port, proto )
31
- "-A Public -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j ACCEPT\n"
32
- end
33
- end
34
- end
30
+ def public_ipt( port, proto )
31
+ "-A Public -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j ACCEPT\n"
32
+ end
33
+ end
34
+ end
35
35
  end
data/lib/shutter/os.rb ADDED
@@ -0,0 +1,41 @@
1
+ module Shutter
2
+ class OS
3
+ def initialize
4
+ unless File.exist?('/proc/version')
5
+ @version = "Unknown"
6
+ end
7
+ end
8
+
9
+ def family
10
+ @family ||= ENV['OS'] ? ENV['OS'] : RUBY_PLATFORM.split('-').last
11
+ end
12
+
13
+ def version
14
+ @version ||= IO.read('/proc/version')
15
+ end
16
+
17
+ def linux?
18
+ return family == "linux"
19
+ end
20
+
21
+ def dist
22
+ case version
23
+ when /Red Hat/
24
+ "RedHat"
25
+ when /Debian/
26
+ "Debian"
27
+ when /Ubuntu/
28
+ "Ubuntu"
29
+ else
30
+ "Unknown"
31
+ end
32
+ end
33
+
34
+ def redhat?
35
+ dist == "RedHat"
36
+ end
37
+
38
+ alias :centos? :redhat?
39
+ alias :fedora? :redhat?
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Shutter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -34,6 +34,7 @@ files:
34
34
  - lib/shutter/iptables/iface.rb
35
35
  - lib/shutter/iptables/jail.rb
36
36
  - lib/shutter/iptables/port.rb
37
+ - lib/shutter/os.rb
37
38
  - lib/shutter/version.rb
38
39
  - shutter.gemspec
39
40
  homepage: ''