catflap 0.0.2 → 1.0.1

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.
@@ -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