antispam 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 278c21161c08ebd08f8376df6ddb57fcda33d20d7ae9e9d804a7b3785c23cbae
4
- data.tar.gz: dab176fb46e3d5ecaa6d2c304262adfc4bf612f413b392270e3b44ef03de7147
3
+ metadata.gz: f04775ef37b7cf6a564c81bb3f664dbecf7b638fdf95db9beafd5484e5ceb3e5
4
+ data.tar.gz: bd219f97bc7ff11bf36fe4e98377c0e4b920a93e10f27fa4cae9a170db1d2ab8
5
5
  SHA512:
6
- metadata.gz: 3491eb8c49c91b0cc468440cde3b965ac359d6e3d561e8893a5e48079da0441a2128dd9cb118d30b79e147b8ad79d87ce2df78fcd074217880b1c6f9c4e60748
7
- data.tar.gz: b1d49d286f4bc2d6885e40e7f20b0bd9cdec2f57c608dd443b9c060a8a49ca7799e69f05a0e3e5f422071f385a34fcd39e442a2ee5b5a89f0dfd56425574da5c
6
+ metadata.gz: 18e2653f47965506ef9673c01eb4bc15f1367c253822e8de402f5d1862020b6b60729ae444d03dccb89cf40583263cdef6845bac656512dbc1fb6499596d58cb
7
+ data.tar.gz: 5e19607550a09cc727785ae31fd0bc4221944f2a1a14e2573a43ea4c12969124507e3514dff346d1e8658caf380f2190d0118ced16ef049a3da4c11312126707
data/README.md CHANGED
@@ -1,9 +1,33 @@
1
1
  # Antispam
2
2
  The antispam gem helps prevent spam in your Rails applications by
3
- checking against various antispam blacklists on the web.
4
- You can configure which spam blacklists are checked in your application configuration.
3
+ providing tools that check spam against powerful spam-prevention
4
+ databases, accessible for free.
5
5
 
6
- ## Usage
6
+ The first feature checks against an IP database of spam, allowing you
7
+ to stop spammers who are prolific and have been detected on other websites.
8
+ It relies on the lightning-quick httpbl from Project Honey Pot.
9
+
10
+ The second feature allows you to submit user-provided content to a spam
11
+ checking service that uses machine learning and a database of content to
12
+ determine whether the user's submitted content is spam. It uses the blazing
13
+ fast Defendium API I created to quickly determine if submitted content is
14
+ spam or not. Defendium's [pricing](https://defendium.com/pricing) is free
15
+ for up to 1,000 API calls per day, which should be sufficient for 99% of users.
16
+
17
+ The two features are optional, and you can use either one without the other.
18
+
19
+ ## Spam Content Checking - Usage
20
+
21
+ ```
22
+ result = Antispam::Checker.check(content: @comment.body)
23
+ if result.is_spam?
24
+ redirect_to "/access_denied"
25
+ else
26
+ @comment.save
27
+ end
28
+ ```
29
+
30
+ ## Bad IP Checking - Usage
7
31
 
8
32
  The gem is used by adding this to your ApplicationController.rb
9
33
 
@@ -13,8 +37,29 @@ before_action do
13
37
  end
14
38
  ```
15
39
 
40
+ Codes are from the [httpbl](https://www.projecthoneypot.org/httpbl.php) at projecthoneypot.org
41
+
16
42
  Once the filter is setup, everything else is handled for your application.
17
- The gem will run during any request that is not a GET request.
43
+ By default the gem will run during any request that is not a GET request.
44
+
45
+ When a POST/PATCH/ETC (non-GET) request comes in, the IP blacklist is checked
46
+ to see if the poster is on a spam blacklist. If the poster is on the blacklist
47
+ then the request is automatically blocked and redirected to a captcha page. A
48
+ real user can then enter the captcha to bypass the block. In the future other
49
+ captcha options may be supported, such as mechanical (hashing) captcha and
50
+ other types of invisible captcha.
51
+
52
+ Eventually configurable settings may be in place to give other options when
53
+ a spammy IP is detected, but the current defaults are set to only block spam
54
+ in cases where the blacklist is quite certain the IP is only doing spam.
55
+
56
+ You can change the filter to run during other requests.
57
+
58
+ ```
59
+ before_action do
60
+ check_ip_against_database(ip_blacklists: {default: 'yourcodehere'}, methods: [:get,:post,:put,:patch,:delete])
61
+ end
62
+ ```
18
63
 
19
64
  Blacklist database lookups are cached for 24 hours, and cached results won't need
20
65
  to slowdown your app by additional http requests on the backend.
@@ -27,7 +72,7 @@ You need to add this to your routes.rb
27
72
  mount Antispam::Engine => "/antispam"
28
73
  ```
29
74
  You can see what IP addresses have been blocked by going to /antispam/blocks
30
- but your applicationcontroller must respond to ```is_admin?``` function.
75
+ but your ApplicationController.rb must respond to ```is_admin?``` function.
31
76
 
32
77
 
33
78
  ## Installation
@@ -70,3 +115,14 @@ The gem is available as open source under the terms of the [MIT License](https:/
70
115
  ## Code of Conduct
71
116
 
72
117
  Everyone interacting in the Antispam project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ryankopf/antispam/blob/master/CODE_OF_CONDUCT.md).
118
+
119
+ ## NO WARRANTY
120
+
121
+ THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND,
122
+ EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO,
123
+ ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS,
124
+ ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
125
+ OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE
126
+ ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO
127
+ THE SUBJECT SOFTWARE. THIS SOFTWARE IS PROVIDED "AS IS." IF YOUR JURISDICTION
128
+ DOES NOT ALLOW THESE LIMITATIONS THEN YOU MAY NOT USE THE SOFTWARE.
@@ -17,6 +17,7 @@ module Antispam
17
17
  # GET /challenges/new
18
18
  def new
19
19
  # use in the future for changing code
20
+ head :ok
20
21
  end
21
22
 
22
23
  # PATCH/PUT /challenges/1
@@ -34,6 +34,6 @@
34
34
  </table>
35
35
  </div>
36
36
  <div class="cx">
37
- <%= render template: '/antispam/clears/index.html' %>
37
+ <%= render template: '/antispam/clears/index', formats: :html %>
38
38
  </div>
39
39
  </div>
@@ -2,6 +2,7 @@ require 'resolv'
2
2
  module Antispam
3
3
  module Blacklists
4
4
  class Httpbl
5
+ # Returns a threat-level number, or 0 if no threat / no result.
5
6
  def self.check(ip, key, verbose)
6
7
  threat = 0
7
8
  begin
@@ -15,19 +16,20 @@ module Antispam
15
16
  address = Resolv::getaddress(host)
16
17
  z,days,threat,iptype = address.split('.')
17
18
  Rails.logger.info "Spam located: #{iptype} type at #{threat} threat. (#{ip} - #{address})" if verbose
19
+ threat = threat.to_i
18
20
  # Create or update
19
- if (threat.to_i > 30)
20
- Rails.logger.info "Spamcheck: Very high, over 30!"
21
+ if (threat > 30)
22
+ Rails.logger.info "Spamcheck: Very high, over 30!" if verbose
21
23
  end
22
24
  rescue Exception => e
23
25
  case e
24
26
  when Resolv::ResolvError #Not spam! This blacklist gives an error when there's no spam threat.
25
- Rails.logger.info "Spamcheck: OK! Resolve error means the httpbl does not consider this spam."
27
+ Rails.logger.info "Spamcheck: OK! Resolve error means the httpbl does not consider this spam." if verbose
26
28
  when Interrupt #Something broke while trying to check blacklist.
27
- Rails.logger.info "Spamcheck: Interrupt when trying to resolve http blacklist. Possible timeout?"
29
+ Rails.logger.info "Spamcheck: Interrupt when trying to resolve http blacklist. Possible timeout?" if verbose
28
30
  else # Time Out
29
- Rails.logger.info "Spamcheck: There was an error, possibly a time out, when checking this IP."
30
- Rails.logger.info e.to_s
31
+ Rails.logger.info "Spamcheck: There was an error, possibly a time out, when checking this IP." if verbose
32
+ Rails.logger.info e.to_s if verbose
31
33
  end
32
34
  end
33
35
  update_old_result(ip, threat)
@@ -0,0 +1,31 @@
1
+ module Antispam
2
+ module Checker
3
+ # Checks content for spam
4
+ # check(options)
5
+ # Usage: check({content: "No spam here", providers: { defendium: 'MY_API_KEY'}})
6
+ def self.check(options = {})
7
+ # Default provider. 'YOUR_KEY' works temporarily, giving a warning but also giving results
8
+ # eventually add something to tell users to add their own keys
9
+ # or choose their preferred provider, when more provider options are added.
10
+ options[:providers] ||= {defendium: 'YOUR_KEY'}
11
+ Rails.logger.info "Content was nil for spamcheck." if options[:content].nil? && options[:verbose]
12
+ return if options[:content].nil?
13
+ Rails.logger.info "Spamcheckers should be a hash" if (!(options[:providers].is_a? Hash)) && options[:verbose]
14
+ results = []
15
+ options[:providers].each do |spamchecker_name, spamchecker_api_key|
16
+ results.append spamchecker(spamchecker_name).check(options[:content], spamchecker_api_key, options[:verbose])
17
+ # if spamchecker_name == :defendium
18
+ # results.append Antispam::Spamcheckers::Defendium.check(options[:content], spamchecker_api_key, options[:verbose])
19
+ # end
20
+ end
21
+ result = Antispam::SpamcheckResult.new(results)
22
+ return result
23
+ end
24
+ def self.spamchecker(provider)
25
+ class_name = provider.to_s.camelize
26
+ raise Antispam::NoSuchSpamcheckerError unless Antispam::Spamcheckers.const_defined? class_name
27
+ Antispam::Spamcheckers.const_get class_name
28
+ end
29
+ end
30
+ class NoSuchSpamcheckerError < StandardError; end
31
+ end
@@ -0,0 +1,18 @@
1
+ module Antispam
2
+ class SpamcheckResult
3
+ def initialize(results)
4
+ @results = results
5
+ end
6
+ def is_spam?
7
+ @results.select{|x| x > 0}.present?
8
+ end
9
+ end
10
+ class BlacklistResult
11
+ def initialize(results)
12
+ @results = results
13
+ end
14
+ def is_bad?
15
+ @results.select{|x| x > 30}.present?
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ #require 'resolv'
2
+ module Antispam
3
+ module Spamcheckers
4
+ class Defendium
5
+ # Returns a boolean, 1 for spam, 0 for not spam.
6
+ def self.check(content, key, verbose)
7
+ # nethttp2.rb
8
+ require 'uri'
9
+ require 'net/http'
10
+
11
+ uri = URI('https://api.defendium.com/check')
12
+ params = { secret_key: key, content: content }
13
+ uri.query = URI.encode_www_form(params)
14
+
15
+ res = Net::HTTP.get_response(uri)
16
+ if res.is_a?(Net::HTTPSuccess)
17
+ result = res.body.to_json
18
+ if result["warnings"]
19
+ Rails.logger.info result["warnings"]
20
+ end
21
+ if result["result"]
22
+ return 1
23
+ else
24
+ return 0
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,6 +1,7 @@
1
1
  module Antispam
2
2
  module Tools
3
- # before_action :check_ip_against_database
3
+ # Checks spam against an IP database of spammers.
4
+ # Usage: before_action :check_ip_against_database
4
5
  def check_ip_against_database(options = {ip_blacklists: {default: ''}})
5
6
  if (options[:methods])
6
7
  return if request.get? unless options[:methods].include?(:get)
@@ -28,20 +29,19 @@ module Antispam
28
29
  end
29
30
  Rails.logger.info "Completed IP database check. #{ip}" if options[:verbose]
30
31
  end
32
+ # Checks the specific blacklists
31
33
  def check_ip_against_blacklists(ip, lists, verbose)
34
+ results = []
32
35
  lists.each do |provider_name, provider_api_key|
33
- puts "Checking provider: #{provider_name}" if verbose
34
- if provider_name == :httpbl
35
- result = Antispam::Blacklists::Httpbl.check(ip, provider_api_key, verbose)
36
- Rails.logger.info(result) if verbose
37
- if (result > 30)
38
- Block.create(ip: ip, provider: provider_name, threat: result)
39
- redirect_to '/antispam/validate'
40
- end
41
- end
36
+ Rails.logger.info "Checking provider: #{provider_name}" if verbose
37
+ results.append blacklist(provider_name).check(ip, provider_api_key, verbose)
38
+ end
39
+ result = Antispam::BlacklistResult.new(results)
40
+ if result.is_bad?
41
+ Block.create(ip: ip, provider: lists.keys.first, threat: result)
42
+ redirect_to '/antispam/validate'
42
43
  end
43
44
  end
44
-
45
45
  def skip_if_user_whitelisted
46
46
  if respond_to? :current_user
47
47
  if current_user && current_user.respond_to?(:antispam_whitelisted?)
@@ -49,7 +49,11 @@ module Antispam
49
49
  end
50
50
  end
51
51
  end
52
-
53
-
52
+ def blacklist(provider)
53
+ class_name = provider.to_s.camelize
54
+ raise Antispam::NoSuchBlacklistError unless Antispam::Blacklists.const_defined? class_name
55
+ Antispam::Blacklists.const_get class_name
56
+ end
54
57
  end
58
+ class NoSuchBlacklistError < StandardError; end
55
59
  end
@@ -1,3 +1,3 @@
1
1
  module Antispam
2
- VERSION = '0.1.5'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/antispam.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require "antispam/version"
2
2
  require "antispam/engine"
3
3
  require "antispam/tools"
4
+ require "antispam/checker"
4
5
  require "antispam/blacklists/httpbl"
6
+ require "antispam/spamcheckers/defendium"
7
+ require "antispam/results"
5
8
 
6
9
  module Antispam
7
10
  ActiveSupport.on_load(:action_controller) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: antispam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Kopf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-26 00:00:00.000000000 Z
11
+ date: 2023-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.0
19
+ version: 6.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.0
26
+ version: 6.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: image_processing
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: net-http
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Antispam checks DNS blacklists and helps prevent spam on your site.
42
56
  email:
43
57
  - antispam@ryankopf.com
@@ -102,7 +116,10 @@ files:
102
116
  - db/migrate/20210131165122_add_threat_to_antispam_blocks.rb
103
117
  - lib/antispam.rb
104
118
  - lib/antispam/blacklists/httpbl.rb
119
+ - lib/antispam/checker.rb
105
120
  - lib/antispam/engine.rb
121
+ - lib/antispam/results.rb
122
+ - lib/antispam/spamcheckers/defendium.rb
106
123
  - lib/antispam/tools.rb
107
124
  - lib/antispam/version.rb
108
125
  - lib/tasks/antispam_tasks.rake
@@ -129,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
146
  - !ruby/object:Gem::Version
130
147
  version: '0'
131
148
  requirements: []
132
- rubygems_version: 3.1.4
149
+ rubygems_version: 3.4.4
133
150
  signing_key:
134
151
  specification_version: 4
135
152
  summary: A spam prevention gem.