icaprb-filter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0837e275231b622dabdb5b873dc7e241bad263ee
4
+ data.tar.gz: 29a4e6006735b354efdd595ba16957323248451b
5
+ SHA512:
6
+ metadata.gz: 3623f5d18b8c7d5699cb0f45e9cadd76b0fde8e4a5fbd08bfc151766151a5f91078136108fa465eb9eb3bb63d82ed70d1440911e93dc6d91852634f1367780b4
7
+ data.tar.gz: 5877b36f5a61248bc9a9aa4486d5b4df86a57b00cee9fabb0f5092cc44e8e81e1f793b4875325d58c40cc86fb3168751d1e70b19e34f57b2e0cd404b3eb317f2
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /html/
11
+ /.idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in icaprb-filter.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2016, Fabian Franz
2
+ Copyright (c) 2016, Markus Petz
3
+ Copyright (c) 2016, Fabian Mayer
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification,
7
+ are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation and/or
14
+ other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
17
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
+ SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
23
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
@@ -0,0 +1,68 @@
1
+ # ICAPrb::Filter
2
+
3
+ ICAPrb::Filter is a content filter based on ICAPrb::Server. The goal is
4
+ to develop a framework which allows to create any custom filtering of
5
+ any content you would not like to have in your network. This could be
6
+ ads, trackers, malware, adult content and so on.
7
+
8
+ The way to defile rules should feel like configuring a firewall ruleset.
9
+
10
+ Plug ins are automatically detected when they reside in the correct
11
+ namespace and are available to use.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'icaprb-filter'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install icaprb-filter
28
+
29
+ ## Usage
30
+
31
+ First of all, you will need a server which is serving your content
32
+ filter.
33
+
34
+ ```ruby
35
+ require "icaprb/server"
36
+ require "icaprb/filter"
37
+
38
+ s = ICAPServer.new
39
+ # url: echo ist der Service - rechts ist der zu verwendende Service
40
+ s.services['filter'] = ICAPrb::Server::FilterService.new('/path/to/filterconfig')
41
+ s.run
42
+ ```
43
+ You will need to replace the path by the path you use on your local
44
+ machine.
45
+
46
+ Next you will have to write your ruleset:
47
+
48
+ ```ruby
49
+ request_filter do
50
+ end
51
+
52
+ response_filter do
53
+ block 'Block pages may contain samples',content_includes: ['sample']
54
+ block 'Block invalid domains', url_contains: ['.invalid']
55
+ block 'Block hashes of bad file', :check_hashes => ['~/hashes']
56
+ end
57
+ ```
58
+
59
+ ## Development
60
+
61
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
62
+
63
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
64
+
65
+ ## Contributing
66
+
67
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fabianfrz/icaprb-filter.
68
+
@@ -0,0 +1,22 @@
1
+ +ICAPrb::Filter+ is the filter component of +ICAPrb+.
2
+ It aims to be able to filter content based on some matches as well as being able to use plug ins to modify content.
3
+
4
+ Modify Content
5
+
6
+ This feature is useful to remove some specific parts of your traffic.
7
+ So you can remove some scripts (for example trackers and ads) based on theire content instead of the url as an URL can simply be changed.
8
+ So the blocket content can be removed cleanly instead of having a whitespace somewhere on websites.
9
+ The filter framework also supports actions like passing or blocking content.
10
+
11
+ The supported methods are
12
+ * pass:: passes the current state to the client
13
+ (in case the client supports 204 responses and the traffic has not been modified - it will be generated, otherwise the full data
14
+ is sent to the client).
15
+ * block:: sends a message that the content has been blocked
16
+ * modify:: calls a plug in to modify the content depending on the return value the modified flag may be set which makes it impossible to
17
+ create a 204 response. For large files it is a good idea to have a pass rule generating 204 responses before any rule of this
18
+ type to reduce network traffic (and increase performance).
19
+ * custom_action:: reserved for plug ins which should interact like a rule type (for example writing files out of the service for
20
+ analysis. For example put it into a queue to test it inside a sandbox to detect malware)
21
+
22
+
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require 'rdoc/task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ RDoc::Task.new do |rdoc|
10
+ rdoc.main = 'README.rdoc'
11
+ rdoc.rdoc_files.include('README.rdoc', 'lib/**/*.rb')
12
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "icaprb/filter"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,40 @@
1
+ #
2
+ require "bundler/setup"
3
+ require "icaprb/server"
4
+ require "icaprb/filter"
5
+ require 'logger'
6
+ include ICAPrb::Server
7
+
8
+ trap('SIGINT') { exit! 0 }
9
+ ########################################################################
10
+ # DIFFERENT WAYS TO RUN THE SERVER #
11
+ ########################################################################
12
+
13
+ # normal socket
14
+ s = ICAPServer.new
15
+ # puts 'Server is running on port 1344. Press CTRL+C to exit...'
16
+
17
+ # squid v4 variant
18
+ #options = {secure: true,
19
+ # certificate: '../cert.pem',
20
+ # key: '../key.pem',
21
+ # tls_socket: true}
22
+ #s = ICAPServer.new('localhost',11344,options)
23
+ # puts 'Server is running on port 11344. Press CTRL+C to exit...'
24
+
25
+ # rfc 3507 variant
26
+ #options = {secure: true,
27
+ # certificate: '../cert.pem',
28
+ # key: '../key.pem',
29
+ # tls_socket: false}
30
+ #s = ICAPServer.new('localhost',1344,options)
31
+ puts 'Server is running on port 1344. Press CTRL+C to exit...'
32
+
33
+ ########################################################################
34
+ s.logger.level = Logger::DEBUG
35
+ # TIMEOUT:
36
+ # timeout_in_seconds = 10
37
+ # s.services['filter'] = ICAPrb::Server::FilterService.new('~/conf/conf.conf',timeout_in_seconds)
38
+ s.services['filter'] = ICAPrb::Server::FilterService.new('~/conf/conf.conf')
39
+
40
+ s.run
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'icaprb/filter/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'icaprb-filter'
8
+ spec.version = ICAPrb::Filter::VERSION
9
+ spec.authors = ['Fabian Franz']
10
+ spec.email = ['fabian.franz@students.fh-hagenberg.at']
11
+
12
+ spec.summary = %q{Filter framework for ICAPrb-server. Does not work standalone. This gem includes
13
+ a framework to create a content filter which allows to filter content instead of only the
14
+ urls. It is extensible by plug ins. For example it can be used to enforce your companies
15
+ network usage policies at the proxy.}
16
+ spec.homepage = 'https://github.com/fabianfrz/ICAPrb-Filter'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'nokogiri', '~> 1.6', '>= 1.6.7'
24
+ spec.add_dependency 'uirusu' # Virustotal public api
25
+ spec.add_dependency 'pdf-reader', '~> 1.4'
26
+ spec.add_dependency 'chunky_png'
27
+ spec.add_dependency 'icaprb-server'
28
+ spec.add_dependency 'rest-client'
29
+ # spec.add_dependency 'ruby-filemagic', '~> 0.7.1'
30
+ spec.add_development_dependency 'bundler', '~> 1.11'
31
+ spec.add_development_dependency 'rake'
32
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
+ end
@@ -0,0 +1,189 @@
1
+ require "icaprb/filter/version"
2
+ # All filter types
3
+ require "icaprb/filter/solution"
4
+ require "icaprb/filter/service"
5
+ require 'logger'
6
+
7
+ # ICAPrb
8
+ module ICAPrb
9
+ # Filter module
10
+ module Filter
11
+ # Exception which is thrown when the configuration file is invalid
12
+ class ConfigurationLoadError < StandardError
13
+ end
14
+ # Response mod filters+plugins
15
+ @resp_mod = nil
16
+ # Temporary during reading
17
+ @temp_reps_mod = nil
18
+ # Request mod filters+plugins
19
+ @req_mod = nil
20
+ # Temporary during reading
21
+ @temp_req_mod = nil
22
+
23
+ # set the configuration mode to request filter so the rules will know that they are request filter rules.
24
+ # It takes a block which is executed while the filter_type is set up.
25
+ def self.request_filter
26
+ @filter_type = :request_mod
27
+ yield
28
+ @filter_type = nil
29
+ end
30
+
31
+ # set the configuration mode to response filter so the rules will know that they are response filter rules.
32
+ # It takes a block which is executed while the filter_type is set up.
33
+ def self.response_filter
34
+ @filter_type = :response_mod
35
+ yield
36
+ @filter_type = nil
37
+ end
38
+
39
+ # returns the filters
40
+ def self.get_filters
41
+ return @filters
42
+ end
43
+
44
+ # creates a new block rule with the parameters
45
+ # +description+:: description of the rule, so it can be logged and the admin can troubleshoot the ruleset.
46
+ # +action+:: do something
47
+ #
48
+ # raises a ConfigurationLoadError if it is called outside of request_filter or response_filter
49
+ def self.block(description, action)
50
+ puts "============================="
51
+ puts "BLOCK: #{description}, ACTION NAME: #{action.keys.first}"
52
+ if @filter_type == :request_mod
53
+ puts "TYPE: REQUEST"
54
+ elsif @filter_type == :response_mod
55
+ puts "TYPE: RESPONSE"
56
+ else
57
+ raise ConfigurationLoadError, "used param 'block' without a filter type"
58
+ end
59
+ # Check if action name exists and create it
60
+ found_name = false
61
+ @valid_filters.each { |filter|
62
+ if filter[:name].to_s == action.keys.first.to_s
63
+ found_name = true
64
+ new_filter = {:name => action.keys.first,
65
+ :object => filter[:class].new(@filter_type, action[action.keys.first]),
66
+ :description => description}
67
+ if @filter_type == :request_mod
68
+ @temp_req_mod << new_filter
69
+ elsif @filter_type == :response_mod
70
+ @temp_resp_mod << new_filter
71
+ end
72
+ break
73
+ end
74
+ }
75
+ unless found_name
76
+ raise ConfigurationLoadError, "Unknown filter type '" + action.keys.first.to_s + "' "
77
+ end
78
+ end
79
+ # Load a modifiying rule
80
+ # +description+:: Description of the rule
81
+ # +action+:: Name of the plugin to use
82
+ # +match+:: Parameters for the plugin
83
+ def self.modify(description, action, match={})
84
+ puts "============================="
85
+ puts "MODIFY/CUSTOM: #{description}, ACTION NAME: #{action.to_s}"
86
+ if @filter_type == :request_mod
87
+ puts "TYPE: REQUEST"
88
+ elsif @filter_type == :response_mod
89
+ puts "TYPE: RESPONSE"
90
+ else
91
+ raise ConfigurationLoadError, "used param 'block' without a filter type"
92
+ end
93
+ # Check if action name exists and create it
94
+ found_name = false
95
+ @valid_plugins.each { |plugin|
96
+ if plugin[:name].to_s == action.to_s
97
+ found_name = true
98
+ # Check if given plugin supports filter type
99
+ unless plugin[:class]::MODES.include? @filter_type
100
+ raise ConfigurationLoadError, 'Plugin ' + action.to_s + ' does not support filter type'
101
+ end
102
+ new_plugin = {:name => action,
103
+ :object => plugin[:class].new(@filter_type, match[match.keys.first]),
104
+ :description => description}
105
+ if @filter_type == :request_mod
106
+ @temp_req_mod << new_plugin
107
+ elsif @filter_type == :response_mod
108
+ @temp_resp_mod << new_plugin
109
+ end
110
+ end
111
+ }
112
+ unless found_name
113
+ raise ConfigurationLoadError, 'Unknown plugin type'
114
+ end
115
+ end
116
+ # Custom action, alias for modify
117
+ # The reason for it being a simple alias is that it may not modify
118
+ # its content, for example a virustotal scan takes too long
119
+ # so we pass it through anyway, but the scan results is saved in a log file
120
+ # May modify the content, but default behaviour should be that it doesn't
121
+ # +description+:: Description of the function
122
+ # +action+:: Name of the action in the configuration file
123
+ # +match+:: Attributes
124
+ def self.custom_action(description, action, match={})
125
+ self.modify(description, action, match)
126
+ end
127
+
128
+ # Placeholder if user wants to write pass, doesn't do anything
129
+ # For future expansion: Add conditionals to the rules ==> rewrite pass
130
+ def self.pass()
131
+ end
132
+ # Delete current filters
133
+ # Simple reset for tests of configuration files
134
+ def self.delete_filters()
135
+ @req_mod = nil
136
+ @resp_mod = nil
137
+ @temp_req_mod = nil
138
+ @temp_resp_mod = nil
139
+ @filter_type = nil
140
+ end
141
+
142
+ # Try to load the configureation file from path.
143
+ # If everything works as expected, the new filter rules are set,
144
+ # otherwise an error is raised if the configuration file is invalid and no previous configuration is available
145
+ # which would lead into an empty config or the loading will fail with an error on the log.
146
+ # +path+:: Path to the configuration file
147
+ def self.load_filters(path)
148
+ # puts are required because no logger is given when the service is created
149
+ # Setup objects to be written into
150
+ puts 'Trying to read new configuration'
151
+ # Set valid plugins and filters, has to done for each reload
152
+ @valid_filters = ICAPrb::Filters.get_filters
153
+ @valid_plugins = ICAPrb::Filters.get_plugins
154
+ # Execute file (we trust the user blindly, assuming that the configuration file is protected sufficiently)
155
+ @temp_resp_mod = []
156
+ @temp_req_mod = []
157
+ begin
158
+ eval(File.read File.expand_path(path))
159
+ rescue StandardError => error
160
+ error_info = "#{error.message} #{error.backtrace}"
161
+ # Initial info couldn't be loaded, shutting down filter framework
162
+ if @resp_mod == nil or @req_mod == nil
163
+ puts "Initial configuration couldn't be loaded: #{error_info}"
164
+ # Non recoverable
165
+ raise ConfigurationLoadError, "Initial configuration couldn't be loaded: #{error_info}"
166
+ else
167
+ puts "Error when reloading the configuration, configuration wasn't changed: #{error_info}"
168
+ # Don't throw an error, we still retain the old configuration
169
+ @temp_resp_mod = nil
170
+ @temp_req_mod = nil
171
+ @filter_type = nil
172
+ return
173
+ end
174
+ end
175
+ # Write data into variables (writing it beforehand is dangerous because the incomplete object may be used
176
+ # for new requests, this allows to reload the configuration during runtime)
177
+ @req_mod = @temp_req_mod
178
+ @resp_mod = @temp_resp_mod
179
+ puts 'Finished reading filter configuration'
180
+ return @req_mod, @resp_mod
181
+ end
182
+
183
+ # Set logger for filter
184
+ # +logger+:: Logger object
185
+ def self.set_logger(logger)
186
+ @logger = logger
187
+ end
188
+ end
189
+ end