]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/commitdiff
Tor: allow enforcing distinct Guard relays or countries
authorPeter Müller <peter.mueller@ipfire.org>
Wed, 4 Nov 2020 21:28:50 +0000 (22:28 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 25 Nov 2020 17:20:51 +0000 (17:20 +0000)
In order to make deanonymisation harder, especially high-risk Tor users
might want to use certain Guard relays only (for example operated by
people they trust), enforce Tor to use Guard relays in certain countries
only (for example countries with very strict data protection laws or
poor diplomatic relations), or avoid Guard relays in certain countries
entirely.

Since Tor sticks to sampled Guards for a long time (usually within the
range of months), restricting those is believed to cause less harm to a
users' anonymity than restricting Exit relays, since their diversity of
a generic Tor user is significantly higher.

This patch extends the Tor CGI for restricting Guard nodes to certain
countries or relays matching certain fingerprints.

Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
html/cgi-bin/tor.cgi

index 78b7333d924ca988e7d0cabd7042b1922ec8b17e..fe91ed399b2b3c0b091d0f68b7afb17f62125089 100644 (file)
@@ -96,6 +96,8 @@ $settings{'TOR_ENABLED'} = 'off';
 $settings{'TOR_SOCKS_PORT'} = 9050;
 $settings{'TOR_EXIT_COUNTRY'} = '';
 $settings{'TOR_USE_EXIT_NODES'} = '';
+$settings{'TOR_GUARD_COUNTRY'} = '';
+$settings{'TOR_USE_GUARD_NODES'} = '';
 $settings{'TOR_ALLOWED_SUBNETS'} = "$netsettings{'GREEN_NETADDRESS'}\/$netsettings{'GREEN_NETMASK'}";
 if (&Header::blue_used()) {
        $settings{'TOR_ALLOWED_SUBNETS'} .= ",$netsettings{'BLUE_NETADDRESS'}\/$netsettings{'BLUE_NETMASK'}";
@@ -178,6 +180,15 @@ if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
                }
        }
 
+       @temp = split(/[\n,]/,$settings{'TOR_USE_GUARD_NODES'});
+       $settings{'TOR_USE_GUARD_NODES'} = "";
+       foreach (@temp) {
+               s/^\s+//g; s/\s+$//g;
+               if ($_) {
+                       $settings{'TOR_USE_GUARD_NODES'} .= $_.",";
+               }
+       }
+
        # Burst bandwidth must be less or equal to bandwidth rate.
        if ($settings{'TOR_RELAY_BANDWIDTH_RATE'} == 0) {
                $settings{'TOR_RELAY_BANDWIDTH_BURST'} = 0;
@@ -281,6 +292,9 @@ END
        @temp = split(",", $settings{'TOR_USE_EXIT_NODES'});
        $settings{'TOR_USE_EXIT_NODES'} = join("\n", @temp);
 
+       @temp = split(",", $settings{'TOR_USE_GUARD_NODES'});
+       $settings{'TOR_USE_GUARD_NODES'} = join("\n", @temp);
+
        print <<END;
                <br>
                <br>
@@ -303,8 +317,57 @@ END
                        </tr>
                </table>
 
-               <br>
-               <br>
+               <br />
+               <br />
+
+               <table width='95%'>
+                       <tr>
+                               <td colspan='4' class='base' bgcolor='$color{'color20'}'><b>$Lang::tr{'tor guard nodes'}</b></td>
+                       </tr>
+                       <tr>
+                               <td colspan='2' class='base' width='55%'></td>
+                               <td colspan='2' class='base' width='45%'>$Lang::tr{'tor use guard nodes'}:</td>
+                       </tr>
+                       <tr>
+                               <td width='50%' colspan='2'>
+                                       <select name='TOR_GUARD_COUNTRY' multiple='multiple'>
+                                               <option value=''>- $Lang::tr{'tor guard country any'} -</option>
+END
+
+               # Convert Guard country strings into lists to make comparison easier
+               my @guard_countries;
+               if ($settings{'TOR_GUARD_COUNTRY'} ne '') {
+                       @guard_countries = split(/\|/, $settings{'TOR_GUARD_COUNTRY'});
+               }
+
+               my @country_codes = &Location::database_countries($db_handle);
+               foreach my $country_code (@country_codes) {
+                       # Convert country code into upper case format.
+                       $country_code = uc($country_code);
+
+                       # Get country name.
+                       my $country_name = &Location::Functions::get_full_country_name($country_code);
+
+                       print "<option value='$country_code'";
+
+                       if ($settings{'TOR_GUARD_COUNTRY'} ne '') {
+                               print " selected" if grep /$country_code/, @guard_countries;
+                       }
+
+                       print ">$country_name ($country_code)</option>\n";
+               }
+
+       print <<END;
+                                       </select>
+                               </td>
+                               <td width='50%' colspan='2'>
+                                       <textarea name='TOR_USE_GUARD_NODES' cols='32' rows='3' wrap='off'>$settings{'TOR_USE_GUARD_NODES'}</textarea>
+                               </td>
+                       </tr>
+               </table>
+
+               <br />
+               <br />
 
                <table width='95%'>
                        <tr>
@@ -321,7 +384,7 @@ END
 END
                my @country_codes = &Location::Functions::get_locations("no_special_locations");
 
-               # Convert Exit/Guard country strings into lists to make comparison easier
+               # Convert Exit country strings into lists to make comparison easier
                my @exit_countries;
                if ($settings{'TOR_EXIT_COUNTRY'} ne '') {
                        @exit_countries = split(/\|/, $settings{'TOR_EXIT_COUNTRY'});
@@ -680,6 +743,30 @@ sub BuildConfiguration() {
                }
                print FILE "SocksPolicy reject *\n" if (@subnets);
 
+               if ($settings{'TOR_GUARD_COUNTRY'} ne '') {
+                       $strict_nodes = 1;
+                       my $countrylist;
+
+                       for my $singlecountry (split(/\|/, $settings{'TOR_GUARD_COUNTRY'})) {
+                               if ($countrylist eq '') {
+                                       $countrylist = "{" . lc $singlecountry . "}";
+                               } else {
+                                       $countrylist = $countrylist . "," . "{" . lc $singlecountry . "}";
+                               }
+                       }
+
+                       print FILE "EntryNodes $countrylist\n";
+               }
+
+               if ($settings{'TOR_USE_GUARD_NODES'} ne '') {
+                       $strict_nodes = 1;
+
+                       my @nodes = split(",", $settings{'TOR_USE_GUARD_NODES'});
+                       foreach (@nodes) {
+                               print FILE "EntryNode $_\n";
+                       }
+               }
+
                if ($settings{'TOR_EXIT_COUNTRY'} ne '') {
                        $strict_nodes = 1;
                        my $countrylist;