selenium_tor 1.4.0 → 1.5.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.
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