selenium_tor 1.4.0 → 1.5.1

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: 89802b75ed87505f2f9ba8671aeb649b66db4a7fd63a9f44f695acc3b7bcce18
4
- data.tar.gz: fcaa6f71fbac4a9ba4a165ab6919c1c7160fb01b0d3d79a8b2c4db55bd65dec0
3
+ metadata.gz: 9c45649309a0d50821238c2dc502b8e1d5e9f2137a24229cd09c4493aa45ea7d
4
+ data.tar.gz: 56177ff95c346118c5497bc0cfa44a1de83d3705be663596d7aefe8ab475e72e
5
5
  SHA512:
6
- metadata.gz: 01fb59e8597bf62a649785f65ea8c616479384e8a18c376954981d7dedc978cb063dca1f8ce280a23dfbe1c05a0ca538e8115b3c6b4c5fd4a1c8cb56ebf173fd
7
- data.tar.gz: 91cb32514aef461e29695b1e5e5470e439c8e0c407ec19229adb84b9207e7febc94cde429c235a809ad4db8cca37fb57c6f857d909b5589e408970bbbdadfb0e
6
+ metadata.gz: 3d8ed9f5b35b852ea189f755d33af91676cbfb3b5750506b9955653220ec5bda98303dfe89dbf2ff850bdbc538d37d26169e5a5b74ff3f10cb3bfeff04b511e9
7
+ data.tar.gz: 4628ebe827ab1ef4004c7c5c09d1126a2aecb5ce53f52c652221ec76da36890f5ab9bb8df46b44da331a00d6a8a5eb8b94750ef8bdf84df6849d31cc1782f56f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## master (unreleased)
2
2
 
3
+ ## [1.5.1] - 2024-09-02
4
+
5
+ Fix load path error in LibxulPatchable module
6
+
7
+ ## [1.5.0] - 2024-08-31
8
+
9
+ ### Bug fixes
10
+
11
+ * [#15](https://gitlab.com/matzfan/selenium-tor/-/issues/15)
12
+ * [#16](https://gitlab.com/matzfan/selenium-tor/-/issues/16)
13
+ * [#17](https://gitlab.com/matzfan/selenium-tor/-/issues/17)
14
+
15
+ ### New features
16
+
17
+ * add ability to patch libxul.so to avoid webdriver fingerprint detection
18
+
3
19
  ## [1.4.0] - 2024-08-07
4
20
 
5
21
  ### Breaking changes
data/README.md CHANGED
@@ -49,6 +49,19 @@ The location of the TBB is not expected to change during code execution.
49
49
 
50
50
  Tor Selenium is tested on **Linux only** right now.
51
51
 
52
+ ### Patching libxul.so
53
+
54
+ A configuration option to patch the libxul.so packaged with Tor Browser is provided. This has the effect of preventing websites from fingerprinting Selenium-driven Tor Browser via a JS call to `navigator.webdriver`:
55
+ ```ruby
56
+ Tor::Driver.libxul_patched? # is Tor Browser's libxul.so patched?
57
+ # => false
58
+ Tor::Driver.patch_libxul # patch libxul.so
59
+ Tor::Driver.libxul_patched?
60
+ # => true
61
+ Tor::Driver.unpatch_libxul # revert the patch and restore the libxul.so packaged with Tor Browser
62
+ ```
63
+ The patcher uses the `[bsdiff](https://www.daemonology.net/bsdiff)` package, which must be installed on your system.
64
+
52
65
  ## Usage
53
66
  ```ruby
54
67
  require 'selenium_tor'
@@ -63,7 +76,7 @@ A separate tor process is used for each driver. Failure to call `Driver#quit` af
63
76
 
64
77
  In addition to the regular Firefox options, a :tor_opts key may be passed to an instance of `Tor::Options` with a hash of tor options. All valid tor options are recognized - see `man tor`. For convenience, "SocksPort" and "ControlPort" options may be set using snake_case symbols - i.e. :socks_port and :control_port. Additionally, a :tor_opts timeout value may be set with the :timeout key. This overrides the default time allowed for the tor process to bootstrap (10 seconds).
65
78
 
66
- ### Multiple driver instances (headless drivers only)
79
+ ### Multiple driver instances
67
80
 
68
81
  Running multiple tor processes requires that each uses different ports for SocksPort (and ControlPort, if used). These must be passed using the `:tor_opts` key. An example using the [Parallel gem](https://rubygems.org/gems/parallel):
69
82
  ```ruby
@@ -121,6 +134,7 @@ A number of constants are set during driver initialization based upon values fou
121
134
  Tor::TBB_DIR # path to the TBB root directory
122
135
  Tor::TBB_BROWSER_DIR # path to the 'Browser' directory in the above
123
136
  Tor::TBB_BINARY_PATH # path to the firefox binary
137
+ Tor::TBB_TOR_BINARY_PATH # path to the bundled tor binary
124
138
  Tor::TBB_PROFILE_DIR # path to the default profile directory
125
139
  Tor::TBB_EXTENSIONS_DIR # path to the 'extensions' directory in the above
126
140
  Tor::TBB_VERSION # the version installed, e.g. "13.0.1", note: driver.capabilities.browser_version returns the Firefox version Tor Browser is based on
data/lib/tor/driver.rb CHANGED
@@ -4,6 +4,7 @@ require 'open-uri'
4
4
  require_relative '../service'
5
5
  require_relative '../options'
6
6
  require_relative '../firefox_prefs'
7
+ require_relative 'libxul_patchable'
7
8
  require_relative 'profile'
8
9
  require_relative 'tor_process'
9
10
 
@@ -15,6 +16,8 @@ module Selenium
15
16
 
16
17
  # tor driver
17
18
  class Driver < DelegateClass(DriverDelegate)
19
+ extend LibxulPatchable
20
+
18
21
  TORRC_PATH_PREF = 'extensions.torlauncher.torrc_path'
19
22
  TORRC = 'torrc'
20
23
  BROWSER_SECURITY_LEVEL_PREF = 'browser.security_level.security_slider'
@@ -73,6 +76,7 @@ module Selenium
73
76
  @tor_process = tor_process(opts)
74
77
  @tor_process.start_tor(timeout: timeout)
75
78
  rescue Tor::TorProcess::TorProcessError => e
79
+ instance_variable_get(:@instance)&.quit # avoids hanging firefox.real process
76
80
  raise Error::WebDriverError, e
77
81
  end
78
82
 
@@ -0,0 +1,13 @@
1
+ ---
2
+ 13.5.2:
3
+ unpatched_libxul: b2f8b3fd25466bd3ffa12fb34b422767b28e09577d5714d6d0c97f695dac15dc
4
+ patched_libxul: 7f761479c2d0307b97023455cfd7811b5749690302f54508b247720105dd0a3b
5
+ patch_checksum: 695f7534586c757781bd33a6dbc627cfe62d010edce20e5754fa5efff7aa80d0
6
+ 14.0a2:
7
+ unpatched_libxul: e0eda8db975fe315e9be32b3bf95ee62767c60ee34deac97a7163f8ab0480dc9
8
+ patched_libxul: ed05f9c383f4ecbce69d978aefc0625c44874193707ebe11166e714b3e2b4f64
9
+ patch_checksum: 0cf817f97bdbe51fba5ad61d566934c9ebdda8fce5540bc803aeca23e0ac3e8b
10
+ 14.0a3:
11
+ unpatched_libxul: f448fc180b547d622b969fe170028408f75493cf95be5e4c1180594daec2226b
12
+ patched_libxul: 337a4ef0e723069695294b37a4843126529c44e2bc4f90b1533b547100355db3
13
+ patch_checksum: 08dd8cab30c4416adf7ab6411e1346dce4a8b6f42e4c410adcd5bc63a71506e5
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+ require 'json'
5
+ require 'open-uri'
6
+ require_relative 'options' # module needs access to consts therein defined
7
+
8
+ module Selenium
9
+ module WebDriver
10
+ module Tor
11
+ # methods to patch/unpatch libxul.so
12
+ module LibxulPatchable
13
+ class LibxulPatchableError < StandardError; end
14
+
15
+ # PATCH_REPO = 'https://gitlab.com/matzfan/keymaster/-/releases' # TODO
16
+ LIBXUL_CHECKSUMS = YAML.load_file(File.join(__dir__, 'libxul_checksums.yml'))[Tor::TBB_VERSION]
17
+ PATCH_REPO = 'https://gitlab.com/matzfan/keymaster/-/raw/main/patches/tor-browser'
18
+ ISSUES_URL = 'https://gitlab.com/matzfan/keymaster/-/issues'
19
+
20
+ def libxul_patched?
21
+ libxul_checksum = checksum_for Tor::TBB_LIBXUL
22
+ return true if patched_libxul_checksum_for_version == libxul_checksum
23
+ return false if unpatched_libxul_checksum_for_version == libxul_checksum
24
+
25
+ raise LibxulPatchableError, 'Unrecognized libxul.so'
26
+ end
27
+
28
+ def patch_libxul
29
+ return if libxul_patched?
30
+
31
+ patchfile = fetch_patchfile
32
+ valid? patchfile
33
+ FileUtils.mv Tor::TBB_LIBXUL, libxul_original # rename libxul.so
34
+ execute_patch patchfile
35
+ FileUtils.cp libxul_patched, Tor::TBB_LIBXUL
36
+ rescue OpenURI::HTTPError
37
+ raise LibxulPatchableError, "No patch for #{Tor::TBB_VERSION}, please raise an issue at #{ISSUES_URL}"
38
+ end
39
+
40
+ def unpatch_libxul
41
+ return unless libxul_patched?
42
+
43
+ FileUtils.mv libxul_original, Tor::TBB_LIBXUL
44
+ end
45
+
46
+ private
47
+
48
+ def libxul_original
49
+ "#{Tor::TBB_LIBXUL}.ORIGINAL"
50
+ end
51
+
52
+ def libxul_patched
53
+ "#{Tor::TBB_LIBXUL}.PATCHED"
54
+ end
55
+
56
+ def valid?(patchfile)
57
+ msg = "Invalid patch for #{Tor::TBB_VERSION}, please raise an issue at #{ISSUES_URL}"
58
+ raise LibxulPatchableError, msg unless patch_checksum_for_version == checksum_for(patchfile)
59
+ end
60
+
61
+ def execute_patch(patchfile)
62
+ raise LibxulPatchableError, 'bspatch not found, please install bsdiff' if `which bspatch`.empty?
63
+
64
+ `bspatch #{libxul_original} #{libxul_patched} #{patchfile}`
65
+ end
66
+
67
+ def unpatched_libxul_checksum_for_version
68
+ LIBXUL_CHECKSUMS['unpatched_libxul']
69
+ end
70
+
71
+ def patched_libxul_checksum_for_version
72
+ LIBXUL_CHECKSUMS['patched_libxul']
73
+ end
74
+
75
+ def patch_checksum_for_version
76
+ LIBXUL_CHECKSUMS['patch_checksum']
77
+ end
78
+
79
+ def checksum_for(file)
80
+ Digest::SHA256.file(file).hexdigest
81
+ end
82
+
83
+ def fetch_patchfile
84
+ tmp = Tempfile.new.tap(&:binmode)
85
+ URI.parse(patch_url).open('rb') do |f|
86
+ tmp.write(f.read)
87
+ tmp.tap(&:flush)
88
+ end
89
+ tmp.path
90
+ end
91
+
92
+ def patch_url
93
+ File.join PATCH_REPO, "#{Tor::TBB_VERSION}.patch"
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
data/lib/tor/options.rb CHANGED
@@ -15,8 +15,10 @@ module Selenium
15
15
 
16
16
  Tor::TBB_DIR = ENV.fetch('TOR_BROWSER_ROOT_DIR', nil) || DEFAULT_TBB_DIR
17
17
  Tor::TBB_BROWSER_DIR = File.join Tor::TBB_DIR, 'Browser'
18
+ Tor::TBB_LIBXUL = File.join Tor::TBB_BROWSER_DIR, 'libxul.so'
18
19
  Tor::TBB_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, 'firefox'
19
20
  Tor::TBB_TOR_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Tor tor]
21
+ Tor::TBB_TOR_DATA_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Tor]
20
22
  Tor::TBB_PROFILE_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Browser profile.default]
21
23
  Tor::TBB_EXTENSIONS_DIR = File.join Tor::TBB_PROFILE_DIR, 'extensions'
22
24
  Tor::TBB_VERSION = JSON.parse(File.read(File.join(Tor::TBB_BROWSER_DIR, 'tbb_version.json')))['version']
data/lib/tor/torrc.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'options' # for Tor::TBB_TOR_BINARY_PATH
3
+ require_relative 'options'
4
4
 
5
5
  module Selenium
6
6
  module WebDriver
@@ -36,7 +36,13 @@ module Selenium
36
36
  private
37
37
 
38
38
  def write_default_config
39
- write_to_config DEFAULT_PORTS.merge('DataDirectory' => @data_dir)
39
+ write_to_config DEFAULT_PORTS.merge(default_config)
40
+ end
41
+
42
+ def default_config
43
+ { 'DataDirectory' => @data_dir,
44
+ 'GeoIPFile' => File.join(TBB_TOR_DATA_DIR, 'geoip'),
45
+ 'GeoIPv6File' => File.join(TBB_TOR_DATA_DIR, 'geoip6') }
40
46
  end
41
47
 
42
48
  def validate_torrc_options(hash)
data/lib/tor/version.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Selenium
4
4
  module WebDriver
5
5
  module Tor
6
- VERSION = '1.4.0'
6
+ VERSION = '1.5.1'
7
7
  end
8
8
  end
9
9
  end
data/tmp/.placeholder ADDED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium_tor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - MatzFan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-07 00:00:00.000000000 Z
11
+ date: 2024-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver
@@ -47,6 +47,8 @@ files:
47
47
  - lib/selenium_tor.rb
48
48
  - lib/service.rb
49
49
  - lib/tor/driver.rb
50
+ - lib/tor/libxul_checksums.yml
51
+ - lib/tor/libxul_patchable.rb
50
52
  - lib/tor/options.rb
51
53
  - lib/tor/profile.rb
52
54
  - lib/tor/system_tor.rb
@@ -56,6 +58,7 @@ files:
56
58
  - lib/tor/version.rb
57
59
  - selenium_tor.gemspec
58
60
  - sig/tor.rbs
61
+ - tmp/.placeholder
59
62
  homepage: https://gitlab.com/matzfan/selenium-tor
60
63
  licenses:
61
64
  - MIT