catflap 0.0.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,21 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ Style/SignalException:
4
+ Enabled: false
5
+ StyleGuide: http://relaxed.ruby.style/#stylesignalexception
6
+
7
+ Style/RegexpLiteral:
8
+ MaxSlashes: 0
9
+
10
+ Metrics/AbcSize:
11
+ Max: 50
12
+
13
+ Metrics/CyclomaticComplexity:
14
+ Max: 22
15
+
16
+ Metrics/MethodLength:
17
+ Max: 42
18
+
19
+ Metrics/PerceivedComplexity:
20
+ Max: 12
21
+
@@ -0,0 +1,7 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2016-02-24 16:27:57 +0700 using RuboCop version 0.27.1.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at Nicholas.Cowham@corbis.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in catflap.gemspec
4
+ gemspec
5
+ gem 'pry', '~> 0.10.3'
6
+ gem 'yard', '~> 0.8.7.6'
7
+ gem 'redcarpet', '~> 3.3', '>= 3.3.4'
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ catflap (1.0.0)
5
+ json (>= 1.8.3)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.1.0)
11
+ diff-lcs (1.2.5)
12
+ json (1.8.3)
13
+ method_source (0.8.2)
14
+ pry (0.10.3)
15
+ coderay (~> 1.1.0)
16
+ method_source (~> 0.8.1)
17
+ slop (~> 3.4)
18
+ rake (10.5.0)
19
+ redcarpet (3.3.4)
20
+ rspec (3.4.0)
21
+ rspec-core (~> 3.4.0)
22
+ rspec-expectations (~> 3.4.0)
23
+ rspec-mocks (~> 3.4.0)
24
+ rspec-core (3.4.2)
25
+ rspec-support (~> 3.4.0)
26
+ rspec-expectations (3.4.0)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.4.0)
29
+ rspec-mocks (3.4.1)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.4.0)
32
+ rspec-support (3.4.1)
33
+ slop (3.6.0)
34
+ yard (0.8.7.6)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ bundler (~> 1.11)
41
+ catflap!
42
+ pry (~> 0.10.3)
43
+ rake (~> 10.0)
44
+ redcarpet (~> 3.3, >= 3.3.4)
45
+ rspec (~> 3.0)
46
+ yard (~> 0.8.7.6)
47
+
48
+ BUNDLED WITH
49
+ 1.11.2
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Nyk Cowham
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Catflap
2
+ =======
3
+ ![alt catflap](https://raw.githubusercontent.com/nyk/catflap/master/ui/images/catflap.png)
4
+
5
+ Catflap provides firewall level protection of multiple ports with a password
6
+ protected web gateway to allow developers and/or site demo/stage reviewers to
7
+ request entry after providing valid authentication credentials. Currently Catflap
8
+ supports Linux running the NetFilter (iptables) kernel-level firewall. However,
9
+ firewall specific implementations are provided as firewall plugin drivers and it
10
+ should be possible to write a separate plugin for the ipfw firewall on Mac OSX
11
+ and other FreeBSD derivatives.
12
+
13
+ Essentially, it is a more user-friendly form of "port knocking". The original
14
+ proof-of-concept implementation was run for almost three years by Demotix, to
15
+ protect development and staging servers from search engine crawlers and other
16
+ unwanted traffic.
17
+
18
+ # Use Cases
19
+ - Prevent web-bots and spiders from crawling and indexing your development,
20
+ demo and staging servers. Since they are protected by a firewall there are no
21
+ back doors.
22
+ - Provide a seamless login to sensitive web backends that may not have their own
23
+ complete user authentication enabled. One example is Kibana, used as a part of
24
+ the ELK logging service.
25
+ - Allow non-technical people to request access through a firewall when they do
26
+ not have a static IP (e.g. from home office) and no access to a VPN.
27
+ - Provides simple to use "port knocking" that does not require any technical
28
+ knowledge of command line networking from end users.
29
+
30
+ # Installation
31
+ Catflap is available as a ruby gem and can be installed with:
32
+
33
+ ```
34
+ gem install catflap
35
+ ```
36
+
37
+ You may also want to download the generic Linux init script
38
+ (https://github.com/nyk/catflap/blob/master/etc/init.d/catflap) and place that
39
+ in /etc/init.d/.
40
+
41
+ # Configuration
42
+ It is advisable to create a configuration file: /usr/local/etc/catflap.yaml
43
+ (this is the default location referenced by the init script, but you can specify
44
+ the location of your configuration file with the --config-file parameter to
45
+ the catflap command line tool.
46
+
47
+ This configuration file is a YAML file and the default configuration is listed
48
+ below:
49
+
50
+ ```YAML
51
+ server:
52
+ listen_addr: '0.0.0.0' # What ip address the catflap server should listen on.
53
+ port: 4777 # The TCP port that the catflap server listens on.
54
+ docroot: './ui' # You can override the ui location.
55
+ endpoint: '/catflap' # The endpoint for the REST API.
56
+ passfile: './etc/passfile.yaml' # Pass phrases are stored here in this file.
57
+ token_ttl: 15 # Expire tokens after 15 seconds.
58
+
59
+ firewall:
60
+ plugin: 'netfilter' # Options are netfilter or iptables.
61
+ dports: '80,443' # Lock multiple ports separating them by commas.
62
+ options: # Options are specific to each firewall plugin driver.
63
+ chain: 'CATFLAP' # Two chains will be created <chain>-ALLOW & <chain>-DENY.
64
+ log_rejected: true # Enable logging of rejected requests.
65
+ accept_local: true # This is only set to false only when developers are testing catflap.
66
+ ```
67
+
68
+ Once your configuration is in place you will then want to install the rules and
69
+ initialize catflap. This can be done with the command line tool:
70
+
71
+ ```
72
+ sudo catflap -f /etc/catflap.yaml install
73
+ ```
74
+
75
+ Catflap has a command line tool that you can use to add or remove addresses from
76
+ the access chain and other household maintenance. Just run 'catflap help' to see
77
+ the available options.
78
+
79
+ Now you will want to start the service. If you are using the init.d script this
80
+ is easy:
81
+
82
+ ```
83
+ sudo service catflap start
84
+ ```
85
+
86
+ If not you will need to start it with the command line directly (useful for
87
+ testing and debugging issues):
88
+ ```
89
+ sudo catflap -f /etc/catflap.yaml start
90
+ ```
91
+
92
+ # Gaining Access
93
+ Addresses and address ranges can be added using the command line with the 'add'
94
+ command, but remote users can request that their current IP address be granted
95
+ access by visiting the URL of the website that is being catflapped with their
96
+ web-browser. Catflap will redirect the target port (e.g. port 80) to the
97
+ Catflap port (e.g. 4777), so they will see the Catflap login screen. Once they
98
+ provide a valid pass phrase, their browser will refresh and they will see the
99
+ target website.
100
+
101
+ This is the default configuration, provided by the 'netfilter'
102
+ driver, which uses NAT on the firewall to forward the ports. You can use the
103
+ 'ipfilter' driver instead, if you want to reject or drop packets rather than
104
+ automatically redirect to the Catflap login. The user would instead have to go
105
+ to the Catflap URL directly. However, the default 'netfilter' driver is
106
+ recommended if you want the best and most seamless end-user experience.
107
+
108
+ # Security considerations
109
+ Although we have been careful to avoid application level security vulnerabilities,
110
+ such as shell injection attacks, and no web user submitted data is passed to the
111
+ operating system without being sanitized (i.e. IP addresses are validated as being
112
+ valid IP addresses before being sent to the firewall interface), there are still
113
+ some areas of security concern to be aware of:
114
+ - The web service must run with root privileges, at the very least be run sudo
115
+ as a user with root privileges to add rules to the firewall. Such privileges are
116
+ unavoidable because the firewall runs in the kernel of the operating system.
117
+ A future release will separate the firewall execution process from the web
118
+ server, so the web server will run as an unprivileged user and only the
119
+ 'Executor' process will run with higher privileges on an internal TCP network.
120
+ - The pass phrases in the passfile.yaml file are not encrypted. This file should
121
+ be placed in a private directory owned by root, chmod 600. If an unauthorized user
122
+ can read that file, then you have larger security problems than Catflap :)
123
+ - Unless you use SSL encryption it is not easy, but possible, for a network sniffer to capture
124
+ a valid token and possibly reuse the token to open the port for their own IP
125
+ address. This risk is very much lessened by the use of timestamps to expire
126
+ authentication tokens, but there is still some potential risk exposure. That
127
+ risk is eliminated entirely by encrypting traffic with TLS/SSL.
128
+ - It is recommended to flush the Catflap access rules every day or so (e.g. using
129
+ a cron job that calls 'sudo catflap purge' command). This is analogous to expiring
130
+ user login sessions.
131
+ - If you want to revoke access on a particular pass phrase, you must remove the
132
+ pass phrase from the passfile and ALSO flush the CATFLAP-ALLOW firewall chain, by
133
+ using the 'catflap purge' command, or remove each IP address with the
134
+ 'catflap revoke <ip>' command.
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
5
+
6
+ task default: :spec
@@ -1,82 +1,89 @@
1
1
  #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
3
 
3
4
  require 'optparse'
4
- require 'catflap'
5
+ require 'catflap/command'
5
6
 
7
+ # Parse options
6
8
  options = {}
7
- optparse = OptionParser.new do |opts|
8
- opts.separator ""
9
- opts.separator "Install/Configure/Service options:"
10
- opts.on('-i', '--install', 'Install and initialize the catflap chain') do
11
- options['install'] = true
9
+ OptionParser.new do |opts|
10
+ opts.banner = ''
11
+ opts.on('-d', '--daemonize', 'Run services as background processes') do
12
+ options[:daemonize] = true
12
13
  end
13
- opts.on('-u', '--uninstall', 'Uninstall catflap from iptables') do
14
- options['uninstall'] = true
14
+ opts.on('-f', '--config-file <filepath>', String, 'Use config file' \
15
+ ' to override default values') do |filepath|
16
+ options[:config_file] = filepath
15
17
  end
16
- opts.on('-f', '--config-file <filepath>', String, 'Use config file to override default values') do |filepath|
17
- options['config_file'] = filepath
18
+ opts.on('-V', '--version', 'Display the version of catflap') do
19
+ options[:version] = true
18
20
  end
19
- opts.on('-s', '--start-server', 'Start the web api server daemon') do
20
- options['start_server'] = true
21
+ opts.on('-n', '--noop', 'Do not run destructive operations on firewall') do
22
+ options[:noop] = true
21
23
  end
22
- opts.separator ""
23
- opts.separator "Access rule control options:"
24
- opts.on('-c', '--check <ipaddr>', String, 'Check if an IP address has access alreqdy') do |ip|
25
- options['check'] = ip
24
+ opts.on('-s', '--https', 'Use HTTPS/SSL to start or manage service') do
25
+ options[:https] = true
26
26
  end
27
- opts.on('-a', '--add <ipaddr>', String, 'IP address to which access should be granted') do |ip|
28
- options['add'] = ip
27
+ opts.on('-v', '--verbose', 'Display additional information to screen') do
28
+ options[:verbose] = true
29
29
  end
30
- opts.on('-d', '--delete <ipaddr>', String, 'IP address or range to remove access previously granted') do |ip|
31
- options['del'] = ip
32
- end
33
- opts.on('-F', '--file <filepath>', String, 'Input file of whitelisted IP addresses') do |filepath|
34
- options['filepath'] = filepath
35
- end
36
- opts.on('-x', '--purge', 'Purge all catflap rules from iptables') do
37
- options['purge'] = true
38
- end
39
- opts.on('-l', '--list', 'List catflap access rules') do
40
- options['list'] = true
41
- end
42
- opts.separator ""
43
- opts.separator "Output and process options:"
44
- opts.on('-n', '--noop', 'Do not run the operation on iptables - no operation') do
45
- cf.noop = true
46
- end
47
- opts.on('-p', '--print', 'Print the iptables generated to screen') do
48
- cf.print = true
49
- end
50
- opts.on('-h', '--help', 'Print this help page.') do
30
+ opts.on('-h', '--help', 'Print this help page.') do
31
+ puts "Usage: catflap <command> [<arg>]\n\n"
32
+ puts 'Commands:'
33
+ puts "\tstart \t\t\t Start a catflap server"
34
+ puts "\tstop \t\t\t Stop a catflap server"
35
+ puts "\trestart \t\t\t Restart a catflap server"
36
+ puts "\treload \t\t\t Reload the pass phrases without restarting the server"
37
+ puts "\tstatus \t\t\t Display the status of a catflap server"
38
+ puts "\tinstall \t\t Install and initialize the catflap rule chain"
39
+ puts "\tuninstall \t\t Uninstall catflap rules from firewall"
40
+ puts "\tcheck <ip> \t\t Check if <ip> already has access"
41
+ puts "\tgrant <ip> \t\t Add <ip> to allow access"
42
+ puts "\trevoke <ip> \t\t Remove access for <ip>"
43
+ puts "\tpurge \t\t\t Remove all catflap managed access grants"
44
+ puts "\tbulkload <filename> \t Bulk load a list of IPs from file"
45
+ puts "\tlist \t\t\t Display a list of all catflap managed access grants"
51
46
  puts opts
52
47
  exit 0
53
48
  end
54
- end.parse! ARGV
49
+ end.parse! ARGV # the options are stripped from ARGV after parsing.
50
+ command, arg = ARGV # destructure what is left into a command and its arguments.
51
+
52
+ cli = CfCommand.new options
55
53
 
56
54
  begin
57
- cf = Catflap.new options['config_file']
58
- rescue Psych::SyntaxError
59
- puts "There is a YAML syntax error in your catflap configuration file.\n"
60
- exit 1
61
- rescue NoMethodError
62
- puts "Cannot read the configuration file (#{options['config_file']}) or default file location: /usr/local/etc/catflap.yaml\n"
63
- exit 1
64
- end
65
- unless options['start_server']
66
- begin
67
- cf.purge_rules! if options['purge']
68
- cf.install_rules! if options['install']
69
- cf.uninstall_rules! if options['uninstall']
70
- cf.add_address! options['add'] if options['add']
71
- cf.delete_address! options['del'] if options['del']
72
- cf.add_addresses_from_file! options['filepath'] if options['filepath']
73
- cf.check_address options['check'] if options['check']
74
- cf.list_rules if options['list']
75
- rescue ArgumentError
76
- puts "Invalid Argument: make sure IP address or range is correct (i.e. CIDR format)\n"
55
+ # pass command and arg to command dispatcher.
56
+ status = cli.dispatch_commands command, arg
57
+
58
+ puts status if command == 'version'
59
+
60
+ if command == 'check'
61
+ if status
62
+ puts "The ip '#{arg}' has access GRANTED"
63
+ else
64
+ puts "The ip '#{arg}' does NOT have access"
65
+ end
77
66
  end
78
- else
79
- require 'catflap-http'
80
- CatflapWebserver::start_server cf
81
- end
82
67
 
68
+ if command == 'status'
69
+ if status[:pid] > 0
70
+ puts "Server listening on #{status[:address]}:#{status[:port]}" \
71
+ " <pid:#{status[:pid].to_s.chomp}>"
72
+ else
73
+ puts "Server is not running on #{status[:address]}:#{status[:port]}"
74
+ end
75
+ end
76
+
77
+ rescue Resolv::ResolvError => err
78
+ warn 'Malformed IP address error: ' << err.message
79
+ rescue Psych::SyntaxError => err
80
+ warn 'There is a YAML syntax error in your config file: ' << err.message
81
+ rescue ArgumentError => err
82
+ warn 'Missing argument error: ' << err.message
83
+ rescue IOError => err
84
+ warn 'File error: ' << err.message
85
+ rescue NameError => err
86
+ warn 'Command unknown error: ' << err.message
87
+ rescue StandardError => err
88
+ warn 'There was an error: ' << err.message
89
+ end