catflap 0.0.1.pre → 0.0.2.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|