iptablez 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,106 @@
1
+ module Iptablez
2
+ module Commands
3
+ # The namespace to describe the `iptables` `-X` argument to delete a chain.
4
+ # @author Kent 'picat' Gruber
5
+ module DeleteChain
6
+ # Move on Module
7
+ include MoveOn
8
+
9
+ NO_CHAIN_MATCH_ERROR = 'iptables: No chain/target/match by that name.'.freeze
10
+ CHAIN_NOT_EMPTY = 'iptables: Directory not empty.'.freeze
11
+
12
+ KNOWN_ERRORS = [NO_CHAIN_MATCH_ERROR, CHAIN_NOT_EMPTY].freeze
13
+
14
+ # @api private
15
+ # Determine a given error. Optionally a chain can be used to provide better context.
16
+ private_class_method def self.determine_error(error:, chain: false)
17
+ if error == NO_CHAIN_MATCH_ERROR
18
+ raise ChainExistenceError, "#{chain} doesn't exist!"
19
+ elsif
20
+ raise ChainNotEmpty, "#{chain} is not empty! Will probably need to flush (-F) it to delete it!"
21
+ else
22
+ raise error
23
+ end
24
+ end
25
+
26
+ # Delete all of the user defined chains.
27
+ #
28
+ # @example Basic Usage
29
+ # Iptablez::Commands::DeleteChain.all
30
+ # # => {"dogs"=>true}
31
+ #
32
+ # @example Basic Usage with a Block
33
+ # Iptablez::Commands::DeleteChain.all do |name, result|
34
+ # puts "#{name} has been deleted." if result # true
35
+ # end
36
+ #
37
+ # @yield Each chain name and boolean if it has been successfully deleted.
38
+ # @return [Hash] Key value pairing of each user defined chain and boolean if it has been successfully deleted.
39
+ def self.all(error: false, continue: !error)
40
+ results = {}
41
+ chains(names: Iptablez::Chains.user_defined, continue: continue, fly_by: fly_by) do |name, result|
42
+ yield [name, result] if block_given?
43
+ results[name] = result
44
+ end
45
+ return false if results.empty?
46
+ results
47
+ end
48
+
49
+ # Delete a chain of a given +name+. This is the heart of this module.
50
+ # @param name [String] Single chain +name+.
51
+ # @param error [Boolean] Determine if operations should raise/halt other possible operations with errors.
52
+ # @param continue [Boolean] Determine if operations should continue despite errors.
53
+ #
54
+ # @example Basic Usage
55
+ # Iptablez::Commands::DeleteChain.chain(name: "dogs")
56
+ # # => false
57
+ # Iptablez::Commands::DeleteChain.chain(name: "cats")
58
+ # # => true
59
+ # @example Basic Usage with a Block
60
+ # Iptablez::Commands::DeleteChain.chain(name: "dogs") do |name, result|
61
+ # puts "#{name} deleted!" if result
62
+ # end
63
+ #
64
+ # @yield [String, Boolean] The +name+ of the chain and +result+ of the operation if a block if given.
65
+ # @return [Boolean] The result of the operation.
66
+ #
67
+ # @raise An error will be raised if the +error+ or +continue+ keywords are +true+ and the operation fails.
68
+ def self.chain(name:, error: false, continue: !error)
69
+ name = name.to_s unless name.is_a? String
70
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-X', name.shellescape)
71
+ e.strip! # remove new line
72
+ if s.success?
73
+ yield [name, true] if block_given?
74
+ return true
75
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
76
+ yield [name, false] if block_given?
77
+ return false
78
+ else
79
+ determine_error(chain: name, error: e)
80
+ end
81
+ end
82
+
83
+ # Delete each name is a given array of names.
84
+ # @param names [Array<String>] An array of chains to delete.
85
+ # @param error [Boolean] Determine if operations should raise/halt other possible operations with errors.
86
+ # @param continue [Boolean] Determine if operations should continue despite errors.
87
+ #
88
+ # @example Basic Usage
89
+ # Iptablez::Commands::DeleteChain.chain(names: ["dogs", "whales"])
90
+ # # => {"dogs"=>false, "whales"=>true}
91
+ #
92
+ # @yield [String, Boolean] The name of the chain and result of the operation if a block if given.
93
+ # @return [Hash] Key value pairing of each given chain and the result of the operation.
94
+ def self.chains(names:, error: false, continue: !error)
95
+ results = {}
96
+ names.each do |name|
97
+ results[name] = chain(name: name, continue: continue) do |name, result|
98
+ yield [name, result] if block_given?
99
+ end
100
+ end
101
+ results
102
+ end
103
+
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,72 @@
1
+ module Iptablez
2
+ module Commands
3
+ module FlushChain
4
+ # Move on Module
5
+ include MoveOn
6
+
7
+ NO_CHAIN_MATCH_ERROR = 'iptables: No chain/target/match by that name.'.freeze
8
+ KNOWN_ERRORS = [NO_CHAIN_MATCH_ERROR].freeze
9
+
10
+ # Flush all of the possible `iptables` chains.
11
+ # @example Basic Usage
12
+ # Iptablez::Commands::Flush.all
13
+ # # => {"INPUT"=>true, "FORWARD"=>true, "OUTPUT"=>true}
14
+ # @example Basic Usage with a Block
15
+ # Iptablez::Commands::Flush.all do |name, result|
16
+ # puts "#{name} flushed!" if result
17
+ # end
18
+ def self.all(names: Iptablez::Chains.all, error: false, continue: !error)
19
+ chains(names: names, continue: continue) do |name, result|
20
+ yield [name, result] if block_given?
21
+ end
22
+ end
23
+
24
+ # Flush the rules for a chain of a given `name`. This is the heart of this modules.
25
+ # @todo Document params.
26
+ # @example Basic Usage
27
+ # Iptablez::Commands::Flush.chain(name: "INPUT")
28
+ # # => true
29
+ # Iptablez::Commands::Flush.chain(name: "cats") # not a real chain
30
+ # # => false
31
+ # @example Basic Usage with a Block
32
+ # Iptablez::Commands::Flush.chain(name: "INPUT") do |name, result|
33
+ # puts "#{name} flushed" if result
34
+ # end
35
+ def self.chain(name:, error: false, continue: !error)
36
+ name = name.to_s unless name.is_a? String
37
+ _, e, s = Open3.capture3(Iptablez.bin_path, '-F', name.shellescape)
38
+ e.strip!
39
+ if s.success?
40
+ yield [name, true] if block_given?
41
+ return true
42
+ elsif MoveOn.continue?(continue: continue, message: e, known_errors: KNOWN_ERRORS)
43
+ yield [name, false] if block_given?
44
+ return false
45
+ else
46
+ determine_error(chain: name, error: e)
47
+ end
48
+ end
49
+
50
+ # Flush the rules for multiple chains of their given `names`.
51
+ # @todo Document params.
52
+ # @example Basic Usage
53
+ # Iptablez::Commands::Flush.chains(names: ["dogs", "cats"])
54
+ # # => {"dogs"=>true, "cats"=>false}
55
+ # @example Basic Usage with a Block
56
+ # Iptablez::Commands::Flush.chains(names: ["dogs", "cats"]) do |name, result|
57
+ # puts "#{name} flushed" if result
58
+ # end
59
+ def self.chains(names:, error: false, continue: !error)
60
+ results = {}
61
+ names.each do |name|
62
+ results[name] = chain(name: name, continue: continue) do |name, result|
63
+ yield [name, result] if block_given?
64
+ end
65
+ end
66
+ results
67
+ end
68
+
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,163 @@
1
+ module Iptablez
2
+ module Commands
3
+ # Kent, wtf is this shit?
4
+ # Don't worry about iiiiit bruuuhhhhhvvv.
5
+ # @author Kent 'picat' Gruber
6
+ module ArgumentHelpers
7
+
8
+ def self.wait(seconds: false)
9
+ if seconds # don't wait forever? :P
10
+ { wait: "-w #{seconds}" }
11
+ else
12
+ { wait: "-w" }
13
+ end
14
+ end
15
+
16
+ def self.counters(packets:, bytes:)
17
+ { counters: "-c #{packets} #{bytes}" }
18
+ end
19
+
20
+ def self.fragment
21
+ { fragment: "-f" }
22
+ end
23
+
24
+ def self.destination(dst:, ip: true, port: !ip)
25
+ unless port
26
+ { destination: "-d #{dst}" }
27
+ else
28
+ destination_port(dst: dst)
29
+ end
30
+ end
31
+
32
+ def self.destination_port(dst:)
33
+ { destination_port: "--dport #{dst}" }
34
+ end
35
+
36
+ def self.source(src:, ip: true, port: !ip)
37
+ unless port
38
+ { source: "-s #{src}" }
39
+ else
40
+ source_port(src: src)
41
+ end
42
+ end
43
+
44
+ def self.source_port(src:)
45
+ { source_port: "-sport #{src}" }
46
+ end
47
+
48
+ # @todo
49
+ #def self.ip_range(from:, to:)
50
+ # { ip_range: "-m iprange #{fromt}-#{to}" }
51
+ #end
52
+
53
+ def self.table(name: "filter")
54
+ { table: "-t #{name}" }
55
+ end
56
+
57
+ def self.jump(target:)
58
+ { jump: "-j #{target}" }
59
+ end
60
+
61
+ def self.goto(target:)
62
+ { goto: "-g #{target}" }
63
+ end
64
+
65
+ def self.interface(name:, out: false)
66
+ argument = if out
67
+ "-o"
68
+ else
69
+ "-i"
70
+ end
71
+ { interface: "#{argument} #{name}" }
72
+ end
73
+
74
+ def self.protocol(protocol:)
75
+ { protocol: "-p #{protocol}" }
76
+ end
77
+
78
+ # @example Basic Usage
79
+ # # note how jump: is compared to goto:
80
+ # args = {:goto=>"-g INPUT", :jump=>"INPUT"}
81
+ # # lets normalize that shit
82
+ # Iptablez::Commands::ArgumentHelpers.normalize_arguments(args)
83
+ # # => {:jump=>"-j INPUT", :goto=>"-g INPUT"}
84
+ def self.normalize_arguments(args)
85
+ results = {}
86
+ results[:jump] = normalize_jump(args[:jump])[:jump] if args[:jump]
87
+ results[:goto] = normalize_goto(args[:goto])[:goto] if args[:goto]
88
+ results[:protocol] = normalize_protocol(args[:protocol])[:protocol] if args[:protocol]
89
+ results[:interface]= normalize_interface(args[:interface])[:interface] if args[:interface]
90
+ results[:src] = normalize_source(args[:src])[:source] if args[:src]
91
+ results[:sport] = normalize_source(args[:sport], port: true)[:source_port] if args[:sport]
92
+ results[:dst] = normalize_destination(args[:dst])[:destination] if args[:dst]
93
+ results[:dport] = normalize_destination(args[:dport], port: true)[:destination_port] if args[:dport]
94
+ results
95
+ end
96
+
97
+ def self.normalize_jump(arg)
98
+ if arg["-j"] || arg["--jump"]
99
+ { jump: arg }
100
+ else
101
+ jump(target: arg)
102
+ end
103
+ end
104
+
105
+ def self.normalize_goto(arg)
106
+ if arg["-g"] || arg["--goto"]
107
+ { goto: arg }
108
+ else
109
+ goto(target: arg)
110
+ end
111
+ end
112
+
113
+ def self.normalize_protocol(arg)
114
+ if arg["-p"] # @todo Check || arg["--protocol"]
115
+ { protocol: arg }
116
+ else
117
+ goto(target: arg)
118
+ end
119
+ end
120
+
121
+ def self.normalize_interface(arg, out: false)
122
+ if arg["-i"] || arg["-o"] # @todo
123
+ { interface: arg }
124
+ else
125
+ interface(name: arg, out: out)
126
+ end
127
+ end
128
+
129
+ def self.normalize_table(arg)
130
+ if arg["-t"] || arg["--table"] # @todo
131
+ { table: arg }
132
+ else
133
+ table(name: arg)
134
+ end
135
+ end
136
+
137
+ def self.normalize_destination(arg, port: false)
138
+ if arg["-d"] || arg["--dport"] # @todo
139
+ if port
140
+ { destination_port: arg }
141
+ else
142
+ { destination: arg }
143
+ end
144
+ else
145
+ destination(dst: arg, port: port)
146
+ end
147
+ end
148
+
149
+ def self.normalize_source(arg, port: false)
150
+ if arg["-s"] || arg["--sport"] # @todo
151
+ if port
152
+ { source_port: arg }
153
+ else
154
+ { source: arg }
155
+ end
156
+ else
157
+ source(src: arg, port: port)
158
+ end
159
+ end
160
+
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,11 @@
1
+ module Iptablez
2
+ module Commands
3
+ class ChainExistenceError < ArgumentError; end
4
+
5
+ class ChainNotEmpty < StandardError ; end
6
+
7
+ class InvalidRuleIndexError < StandardError; end
8
+
9
+ class ChainAlreadyExistsError < ArgumentError; end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module Iptablez
2
+ module Commands
3
+ # @todo Document this module. Kind'a important.
4
+ module MoveOn
5
+ # @api private
6
+ # Determine if the method should should move on with its life when things go wrong.
7
+ def self.continue?(continue:, message:, known_errors:, force: false)
8
+ return true if force
9
+ return true if continue && known_errors.include?(message)
10
+ false
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,80 @@
1
+ module Iptablez
2
+ module Commands
3
+ # @todo Add inline document to this.
4
+ module Interface
5
+
6
+ def self.delete_chain(name: false, all: false)
7
+ if name
8
+ DeleteChain.chain(name: name)
9
+ elsif all
10
+ DeleteChain.all
11
+ else
12
+ raise "No chain name/all specified."
13
+ end
14
+ end
15
+
16
+ def self.flush(chain: false, all: true)
17
+ if chain
18
+ Flush.chain(name: chain)
19
+ elsif all
20
+ Flush.all
21
+ else
22
+ raise "No chain/all specified."
23
+ end
24
+ end
25
+
26
+ def self.list(chain: false, all: true, number: false)
27
+ if chain && ! number
28
+ List.chain(name: chain)
29
+ elsif number && chain
30
+ List.number(chain: chain, number: number)
31
+ elsif all
32
+ List.all
33
+ else
34
+ raise "No chain/number/all specified."
35
+ end
36
+ end
37
+
38
+ def self.new_chain(name:)
39
+ NewChain.chain(name: name)
40
+ end
41
+
42
+ def self.policy(target:, chain: false, all: true)
43
+ if chain && target
44
+ Policy.chain(name: chain, target: target)
45
+ elsif all && target
46
+ Policy.all(target: target)
47
+ else
48
+ raise "No chain/target/all specified."
49
+ end
50
+ end
51
+
52
+ def self.rename_chain(from:, to:)
53
+ if from && to
54
+ RenameChain.chain(from: from, to: to)
55
+ else
56
+ raise "No from/to specified."
57
+ end
58
+ end
59
+
60
+ def self.version(full: false)
61
+ if full
62
+ Version.full
63
+ else
64
+ Version.number
65
+ end
66
+ end
67
+
68
+ def self.zero(all: true, chain: false)
69
+ if chain
70
+ Zero.chain(name: chain)
71
+ elsif all
72
+ Zero.all
73
+ else
74
+ raise "No all/chain specified."
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end