catflap 0.0.1.pre → 0.0.2.pre
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/bin/catflap +8 -8
- data/lib/catflap-http.rb +32 -29
- data/lib/catflap.rb +19 -17
- metadata +7 -7
data/bin/catflap
CHANGED
@@ -4,7 +4,7 @@ require 'optparse'
|
|
4
4
|
require 'catflap'
|
5
5
|
|
6
6
|
options = {}
|
7
|
-
optparse = OptionParser.new do|opts|
|
7
|
+
optparse = OptionParser.new do |opts|
|
8
8
|
opts.separator ""
|
9
9
|
opts.separator "Install/Configure/Service options:"
|
10
10
|
opts.on('-i', '--install', 'Install and initialize the catflap chain') do
|
@@ -14,7 +14,7 @@ optparse = OptionParser.new do|opts|
|
|
14
14
|
options['uninstall'] = true
|
15
15
|
end
|
16
16
|
opts.on('-f', '--config-file <filepath>', String, 'Use config file to override default values') do |filepath|
|
17
|
-
options['config_file'] =
|
17
|
+
options['config_file'] = filepath
|
18
18
|
end
|
19
19
|
opts.on('-s', '--start-server', 'Start the web api server daemon') do
|
20
20
|
options['start_server'] = true
|
@@ -53,18 +53,18 @@ optparse = OptionParser.new do|opts|
|
|
53
53
|
end
|
54
54
|
end.parse! ARGV
|
55
55
|
|
56
|
+
cf = Catflap.new options['config_file']
|
56
57
|
unless options['start_server']
|
57
|
-
cf = Catflap.new(options['config_file'])
|
58
58
|
cf.purge_rules! if options['purge']
|
59
59
|
cf.install_rules! if options['install']
|
60
60
|
cf.uninstall_rules! if options['uninstall']
|
61
|
-
cf.add_address!
|
62
|
-
cf.delete_address!
|
63
|
-
cf.add_addresses_from_file!
|
64
|
-
cf.check_address
|
61
|
+
cf.add_address! options['add'] if options['add']
|
62
|
+
cf.delete_address! options['del'] if options['del']
|
63
|
+
cf.add_addresses_from_file! options['filepath'] if options['filepath']
|
64
|
+
cf.check_address options['check'] if options['check']
|
65
65
|
cf.list_rules if options['list']
|
66
66
|
else
|
67
67
|
require 'catflap-http'
|
68
|
-
CatflapWebserver::start_server
|
68
|
+
CatflapWebserver::start_server cf
|
69
69
|
end
|
70
70
|
|
data/lib/catflap-http.rb
CHANGED
@@ -6,7 +6,7 @@ include WEBrick
|
|
6
6
|
|
7
7
|
module CatflapWebserver
|
8
8
|
|
9
|
-
def self.generate_server
|
9
|
+
def self.generate_server port
|
10
10
|
config = {:Port => port}
|
11
11
|
server = HTTPServer.new(config)
|
12
12
|
yield server if block_given?
|
@@ -16,43 +16,49 @@ module CatflapWebserver
|
|
16
16
|
server.start
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.start_server
|
20
|
-
generate_server
|
21
|
-
server.mount
|
19
|
+
def self.start_server cf
|
20
|
+
generate_server cf.port do |server|
|
21
|
+
server.mount '/', Servlet, cf
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
class Servlet < HTTPServlet::AbstractServlet
|
26
|
-
|
26
|
+
|
27
|
+
def initialize server, cf
|
28
|
+
super server
|
29
|
+
@cf = cf
|
30
|
+
end
|
31
|
+
|
32
|
+
def do_GET req, resp
|
27
33
|
# Split the path into piece
|
28
34
|
path = req.path[1..-1].split('/')
|
29
35
|
raise HTTPStatus::OK if path[0] == 'favicon.ico'
|
30
|
-
response_class = CatflapRestService.const_get
|
36
|
+
response_class = CatflapRestService.const_get 'Service'
|
31
37
|
|
32
|
-
if response_class and response_class.is_a?
|
38
|
+
if response_class and response_class.is_a? Class
|
33
39
|
# There was a method given
|
34
40
|
if path[0]
|
35
41
|
response_method = path[0].to_sym
|
36
42
|
# Make sure the method exists in the class
|
37
|
-
raise HTTPStatus::NotFound if !response_class.respond_to?
|
43
|
+
raise HTTPStatus::NotFound if !response_class.respond_to? response_method
|
38
44
|
|
39
45
|
if path[0] == "enter"
|
40
|
-
url = response_class.send
|
41
|
-
resp.set_redirect
|
46
|
+
url = response_class.send response_method, req, resp, @cf
|
47
|
+
resp.set_redirect HTTPStatus::Redirect, url
|
42
48
|
end
|
43
49
|
|
44
50
|
# Remaining path segments get passed in as arguments to the method
|
45
51
|
if path.length > 1
|
46
|
-
resp.body = response_class.send
|
52
|
+
resp.body = response_class.send response_method, req, resp, @cf, path[1..-1]
|
47
53
|
else
|
48
|
-
resp.body = response_class.send
|
54
|
+
resp.body = response_class.send response_method, req, resp, @cf
|
49
55
|
end
|
50
56
|
raise HTTPStatus::OK
|
51
57
|
|
52
58
|
# No method was given, so check for an "index" method instead
|
53
59
|
else
|
54
|
-
raise HTTPStatus::NotFound if !response_class.respond_to?
|
55
|
-
resp.body = response_class.send
|
60
|
+
raise HTTPStatus::NotFound if !response_class.respond_to? :index
|
61
|
+
resp.body = response_class.send :index
|
56
62
|
raise HTTPStatus::OK
|
57
63
|
end
|
58
64
|
else
|
@@ -65,43 +71,40 @@ end
|
|
65
71
|
module CatflapRestService
|
66
72
|
class Service
|
67
73
|
|
68
|
-
|
69
|
-
@@cf.dports = '80,8080,443'
|
70
|
-
|
71
|
-
def self.index()
|
74
|
+
def self.index
|
72
75
|
return "hello world"
|
73
76
|
end
|
74
77
|
|
75
|
-
def self.enter
|
78
|
+
def self.enter req, resp, cf
|
76
79
|
ip = req.peeraddr.pop
|
77
80
|
host = req.addr[2]
|
78
|
-
|
81
|
+
cf.add_address! ip unless cf.check_address ip
|
79
82
|
return "http://" << host << ":80"
|
80
83
|
end
|
81
84
|
|
82
|
-
def self.add
|
85
|
+
def self.add req, resp, cf, args
|
83
86
|
ip = args[0]
|
84
|
-
unless
|
85
|
-
|
87
|
+
unless cf.check_address ip
|
88
|
+
cf.add_address! ip
|
86
89
|
return "#{ip} has been granted access"
|
87
90
|
else
|
88
91
|
return "#{ip} already has access"
|
89
92
|
end
|
90
93
|
end
|
91
94
|
|
92
|
-
def self.remove
|
95
|
+
def self.remove req, resp, cf, args
|
93
96
|
ip = args[0]
|
94
|
-
|
97
|
+
cf.delete_address! ip
|
95
98
|
return "Access granted to #{ip} has been removed"
|
96
99
|
end
|
97
100
|
|
98
|
-
def self.check
|
101
|
+
def self.check req, resp, cf, args
|
99
102
|
ip = args[0]
|
100
103
|
|
101
|
-
if
|
102
|
-
return "#{ip} has access to ports: #{
|
104
|
+
if cf.check_address ip
|
105
|
+
return "#{ip} has access to ports: #{cf.dports}"
|
103
106
|
else
|
104
|
-
return "#{ip} does not have access to ports: #{
|
107
|
+
return "#{ip} does not have access to ports: #{cf.dports}"
|
105
108
|
end
|
106
109
|
end
|
107
110
|
end
|
data/lib/catflap.rb
CHANGED
@@ -2,12 +2,14 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
class Catflap
|
4
4
|
|
5
|
-
attr_accessor :chain, :dports, :print, :noop, :log_rejected
|
5
|
+
attr_accessor :config, :chain, :port, :dports, :print, :noop, :log_rejected
|
6
6
|
|
7
|
-
def initialize
|
8
|
-
@config =
|
9
|
-
@
|
10
|
-
@
|
7
|
+
def initialize config_file
|
8
|
+
@config = {}
|
9
|
+
@config = YAML.load_file config_file if File.readable? config_file
|
10
|
+
@port = @config['server']['port'] || 4777
|
11
|
+
@chain = @config['rules']['chain'] || 'catflap-accept'
|
12
|
+
@dports = @config['rules']['dports'] || '80,443'
|
11
13
|
@print = false
|
12
14
|
@noop = false
|
13
15
|
@log_rejected = true
|
@@ -19,7 +21,7 @@ class Catflap
|
|
19
21
|
output << "iptables -A INPUT -p tcp -m multiport --dports #{@dports} -j #{@chain}\n" # Jump from INPUT chain to the catflap chain
|
20
22
|
output << "iptables -A INPUT -p tcp -m multiport --dports #{@dports} -j LOG\n" if @log_rejected # Log any rejected packets to /var/log/messages
|
21
23
|
output << "iptables -A INPUT -p tcp -m multiport --dports #{@dports} -j DROP\n" # Drop any other packets to the ports on the INPUT chain
|
22
|
-
execute!
|
24
|
+
execute! output
|
23
25
|
end
|
24
26
|
|
25
27
|
def uninstall_rules!
|
@@ -28,46 +30,46 @@ class Catflap
|
|
28
30
|
output << "iptables -X #{@chain}\n" # Remove the catflap chain
|
29
31
|
output << "iptables -D INPUT -p tcp -m multiport --dports #{@dports} -j LOG\n" # Remove the logging rule
|
30
32
|
output << "iptables -D INPUT -p tcp -m multiport --dports #{@dports} -j DROP\n" # Remove the packet dropping rule
|
31
|
-
execute!
|
33
|
+
execute! output
|
32
34
|
end
|
33
35
|
|
34
36
|
def purge_rules!
|
35
37
|
output = "iptables -F #{@chain}"
|
36
|
-
execute!
|
38
|
+
execute! output
|
37
39
|
end
|
38
40
|
|
39
41
|
def list_rules
|
40
42
|
system "iptables -S #{@chain}"
|
41
43
|
end
|
42
44
|
|
43
|
-
def check_address
|
45
|
+
def check_address ip
|
44
46
|
return system "iptables -C #{@chain} -s #{ip} -p tcp -m multiport --dports #{@dports} -j ACCEPT\n"
|
45
47
|
end
|
46
48
|
|
47
|
-
def add_address!
|
49
|
+
def add_address! ip
|
48
50
|
output = "iptables -I #{@chain} 1 -s #{ip} -p tcp -m multiport --dports #{@dports} -j ACCEPT\n"
|
49
|
-
execute!
|
51
|
+
execute! output
|
50
52
|
end
|
51
53
|
|
52
|
-
def delete_address!
|
54
|
+
def delete_address! ip
|
53
55
|
output = "iptables -D #{@chain} -s #{ip} -p tcp -m multiport --dports #{@dports} -j ACCEPT\n"
|
54
|
-
execute!
|
56
|
+
execute! output
|
55
57
|
end
|
56
58
|
|
57
|
-
def add_addresses_from_file!
|
58
|
-
if File.readable?
|
59
|
+
def add_addresses_from_file! filepath
|
60
|
+
if File.readable? filepath
|
59
61
|
output = ""
|
60
62
|
File.open(filepath, "r").each_line do |ip|
|
61
63
|
output << "iptables -I #{@chain} 1 -s #{ip.chomp} -p tcp -m multiport --dports #{@dports} -j ACCEPT\n"
|
62
64
|
end
|
63
|
-
execute!
|
65
|
+
execute! output
|
64
66
|
else
|
65
67
|
puts "The file #{filepath} is not readable!"
|
66
68
|
exit 1
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
70
|
-
def execute!
|
72
|
+
def execute! output
|
71
73
|
if @print then puts output end
|
72
74
|
system output unless @noop
|
73
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: catflap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2.pre
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,8 +11,8 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2013-12-01 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: A simple solution
|
15
|
-
a more robust and secure VPN solution is not available
|
14
|
+
description: A simple solution to provide on-demand service access (e.g. port 80 on
|
15
|
+
webserver), where a more robust and secure VPN solution is not available.
|
16
16
|
email: nyk@demotix.com
|
17
17
|
executables:
|
18
18
|
- catflap
|
@@ -22,7 +22,7 @@ files:
|
|
22
22
|
- lib/catflap.rb
|
23
23
|
- lib/catflap-http.rb
|
24
24
|
- bin/catflap
|
25
|
-
homepage:
|
25
|
+
homepage: https://github.com/nyk/catflap
|
26
26
|
licenses:
|
27
27
|
- MIT
|
28
28
|
post_install_message:
|
@@ -42,11 +42,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 1.3.1
|
44
44
|
requirements:
|
45
|
-
- NetFilters (iptables) installed and working
|
45
|
+
- NetFilters (iptables) installed and working.
|
46
46
|
rubyforge_project:
|
47
47
|
rubygems_version: 1.8.11
|
48
48
|
signing_key:
|
49
49
|
specification_version: 3
|
50
|
-
summary: Manage NetFilter-based rules to grant port access on
|
51
|
-
or REST API requests
|
50
|
+
summary: Manage NetFilter-based rules to grant port access on-demand via commandline
|
51
|
+
or REST API requests.
|
52
52
|
test_files: []
|