rack-tor-tag 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rack/tor_tag.rb +55 -10
  3. metadata +1 -2
  4. data/lib/rack/ip.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63d7e1b87377867aa008c60820bd02ede6f32a17
4
- data.tar.gz: a80f5026ebe074da7ee24dfb0310440f4c1fd1de
3
+ metadata.gz: 1fd11e7a9e96f55497a03c47e8ff355439d6df61
4
+ data.tar.gz: a818227dd6bc4674359eba20faf07ac41161c68d
5
5
  SHA512:
6
- metadata.gz: f1e82ee67fa8cfbb51ccd937fd6a03c09865a74c8af71837643f0b71b4b715d35f378008bea91090a08fb8dc979b041147c66e11e3806558ef1a43a6c553261c
7
- data.tar.gz: 49d6866e945b236496ec8d311d02f7ae598f18d2f646e6c6a53d1cd1ac9067f837c5a1c2c5e8cf080950a4cf53d94d21496ff4d4f3ec408f29409e636d09f368
6
+ metadata.gz: 33499550d86997dcdf5d0a83d2997d10d4688004f850300e2c66d21c97ddec17f13ce184bdda79f2a78327fb90a1d279339fe5211756dbba58904b48156ff13d
7
+ data.tar.gz: 24efd7df0fed9fbfe094869bfdbd72ca233044fab0cf0118e085939363922f3d2e8002669b460d0197d23118d098124ed9c2e36a35be5c35f390ee54a559a96e
data/lib/rack/tor_tag.rb CHANGED
@@ -1,23 +1,68 @@
1
1
  require 'rack'
2
- require 'rack/ip'
2
+ require 'resolv'
3
3
 
4
4
  module Rack
5
5
  class TorTag
6
+ DEFAULT_PARAMS = {
7
+ # You could run your own if you want.
8
+ # https://www.torproject.org/projects/tordnsel.html.en
9
+ :dnsel => 'ip-port.exitlist.torproject.org',
10
+ :host_ips => nil, # will get from env
11
+ :host_port => nil
12
+ }
6
13
 
7
- # DEFAULT_REDIRECT = 'https://sorry.google.com' #We're sorry from Google
8
-
9
- def initialize(app)
14
+ def initialize(app, params = {})
10
15
  @app = app
16
+ @params = DEFAULT_PARAMS.merge(params)
11
17
  end
12
18
 
13
19
  def call(env)
14
- puts "env", env
15
- req = Rack::Request.new(env)
16
- puts "req", req.inspect
17
- # return [302, {'Content-Type' => 'text', 'Location' => DEFAULT_REDIRECT}, [] ] if Rack::IP.new(env['action_dispatch.remote_ip'] || req.ip).is_tor?
18
-
19
- #Normal processing
20
+ ip = env['action_dispatch.remote_ip']
21
+ # Getting the right IP is hard. Let's punt.
22
+ # http://api.rubyonrails.org/classes/ActionDispatch/RemoteIp.html
23
+ # http://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/
24
+ raise 'Must run after ActionDispatch::RemoteIp' if ip.blank?
25
+
26
+ case is_tor?(ip, env)
27
+ when true
28
+ env['tor'] = true
29
+ env['tor_ip'] = ip # stick it elsewhere
30
+ env['action_dispatch.remote_ip'] = '127.0.0.2' # make all Tor IPs look alike
31
+ when false
32
+ env['tor'] = false
33
+ else
34
+ env['tor'] = nil # i.e. unknown
35
+ end
36
+
37
+ # Continue normal processing
20
38
  @app.call(env)
21
39
  end
40
+
41
+ # see https://www.torproject.org/projects/tordnsel.html.en
42
+ def is_tor? ip, env
43
+ # We're a hidden service! Of course it's Tor.
44
+ return true if env['HTTP_HOST'] =~ /\.onion\z/
45
+
46
+ host_ips = @params[:host_ips] || Resolv.getaddresses(
47
+ env['HTTP_HOST'] ? env['HTTP_HOST'].sub(/:.*/,'') : env['SERVER_NAME']).
48
+ select{|i| i[Resolv::IPv4::Regex]} # DNEL only works with IPv4
49
+
50
+ host_ips.each do |host_ip|
51
+ tor_hostname = [reverse_ip_octets(ip), @params[:host_port] || env['SERVER_PORT'], reverse_ip_octets(host_ip), @params[:dnsel]].join('.')
52
+ begin
53
+ return true if (Resolv.getaddress(tor_hostname) == '127.0.0.2')
54
+ rescue Resolv::ResolvError => e
55
+ false # It's supposed to not get a response if it's not a tor host
56
+ end
57
+ end
58
+ false
59
+
60
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
61
+ return nil
62
+ end
63
+
64
+ def reverse_ip_octets(ip)
65
+ ip.to_s.split('.').reverse.join('.')
66
+ end
22
67
  end
23
68
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-tor-tag
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sai
@@ -47,7 +47,6 @@ extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
49
  - lib/rack-tor-tag.rb
50
- - lib/rack/ip.rb
51
50
  - lib/rack/tor_tag.rb
52
51
  homepage: https://makeyourlaws.org
53
52
  licenses: []
data/lib/rack/ip.rb DELETED
@@ -1,34 +0,0 @@
1
- require 'resolv'
2
-
3
- module Rack
4
- class IP
5
-
6
- TOR_POSITIVE_IP = '127.0.0.2' #In case the DNS look up is positive, this is the IP address returned
7
- TOR_DNSEL = 'ip-port.exitlist.torproject.org' #https://www.torproject.org/projects/tordnsel.html.en
8
-
9
- GOOGLE_DNS_ADDR = '8.8.8.8'
10
- GOOGLE_DNS_PORT = '53'
11
-
12
- # client_addr is the address of the remote client we want to test to be an TOR node
13
- # server_addr is the address of a public IP server we want to reach passing through client_addr
14
- # server_port is a TCP port running on server_addr to test for positiviness to TOR network
15
- def initialize(client_addr, server_addr = GOOGLE_DNS_ADDR, server_port=GOOGLE_DNS_PORT)
16
- @client_addr, @server_port, @server_addr = client_addr.to_s, server_port.to_s, server_addr.to_s
17
- end
18
-
19
- def is_tor? #Implements https://www.torproject.org/projects/tordnsel.html.en
20
- Resolv.getaddress(tor_hostname) == TOR_POSITIVE_IP
21
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Resolv::ResolvError => e
22
- false
23
- end
24
-
25
- def tor_hostname
26
- [reverse_ip_octets(@client_addr), @server_port, reverse_ip_octets(@server_addr), TOR_DNSEL].join('.')
27
- end
28
-
29
- def reverse_ip_octets(ip)
30
- ip.split('.').reverse.join('.')
31
- end
32
-
33
- end
34
- end