Local socks proxy Method'''
This method works for removal of proxy settings but is rather lengthy and complicated. In case the user wants to have a look anyhow, please press on Expand on the right.
Since other methods to configure Tor Browser to use system default networking are broken due to Tor Browser changes by upstream, this new local socks proxy method stops [[Dev/anon-ws-disable-stacked-tor|anon-ws-disable-stacked-tor]] local port 9150
redirection to {{project_name_gateway_long}} 9150
(where a Tor SocksPort
is listening). As a replacement, a local socks proxy listens on {{project_name_workstation_short}} local port 9150
which then forwards the traffic using system default networking. In result, if the user is using a VPN inside {{project_name_workstation_short}} or in a VPN-Gateway wretched between {{project_name_gateway_long}} and {{project_name_workstation_short}}, Tor Browser would use the VPN.
In this documentation, Dante is used as a local socks proxy. Development notes are kept on [[Dev/Dante]].
'''1.''' Legacy notices.
* New users, that did not apply instructions from this page again: No special notice.
* Existing users: See below.
A few settings need to be undone.
* A) Previous changes to /etc/environment
as documented previously for other methods need to be undone.
* B) Tor Browser needs to be re-installed. This is because undoing the previous configuration is difficult and [[Unsupported|undocumented]].
'''2.''' Stop default anon-ws-disable-stacked-tor service for port 9150.
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_template}}
Template.
{{CodeSelect|code=
sudo systemctl stop anon-ws-disable-stacked-tor_autogen_port_9150.socket
sudo systemctl stop anon-ws-disable-stacked-tor_autogen_port_9150.service
sudo systemctl stop anon-ws-disable-stacked-tor_autogen__run_anon-ws-disable-stacked-tor_127.0.0.1_9150.sock.socket
sudo systemctl stop anon-ws-disable-stacked-tor_autogen__run_anon-ws-disable-stacked-tor_127.0.0.1_9150.sock.service
}}
'''3.''' Prevent default anon-ws-disable-stacked-tor systemd unit from starting.
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_template}}
Template.
{{CodeSelect|code=
sudo systemctl mask anon-ws-disable-stacked-tor_autogen_port_9150.socket
sudo systemctl mask anon-ws-disable-stacked-tor_autogen_port_9150.service
sudo systemctl mask anon-ws-disable-stacked-tor_autogen__run_anon-ws-disable-stacked-tor_127.0.0.1_9150.sock.socket
sudo systemctl mask anon-ws-disable-stacked-tor_autogen__run_anon-ws-disable-stacked-tor_127.0.0.1_9150.sock.service
}}
'''4.''' Install the local socks proxy server.
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_template}}
Template.
{{box|text=
'''A)''' Add Debian source repository.
{{Open with root rights|filename=
/etc/apt/sources.list.d/debian-src.list
}}
Paste.
{{CodeSelect|code=
deb-src https://deb.debian.org/debian {{Stable_project_version_based_on_Debian_codename}} main contrib non-free
}}
Save and exit.
{{CodeSelect|code=
sudo apt update
}}
'''B)''' Install build dependencies.
{{CodeSelect|code=
sudo apt build-dep dante-server
}}
'''C)''' Get dante source code.
{{CodeSelect|code=
apt-get source dante-server
}}
'''D)''' Open the dante accesscheck.c source file.
{{CodeSelect|code=
mousepad ~/dante-1.4.2+dfsg/sockd/accesscheck.c
}}
Paste the contents. Here we rewrite the authentication method to always return true.
For the reasons see [[Dev/Dante]].
{{CodeSelect|code=
/*
* Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008,
* 2009, 2010, 2011, 2012, 2013
* Inferno Nettverk A/S, Norway. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. The above copyright notice, this list of conditions and the following
* disclaimer must appear in all copies of the software, derivative works
* or modified versions, and any portions thereof, aswell as in all
* supporting documentation.
* 2. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by
* Inferno Nettverk A/S, Norway.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Inferno Nettverk A/S requests users of this software to return to
*
* Software Distribution Coordinator or sdc@inet.no
* Inferno Nettverk A/S
* Oslo Research Park
* Gaustadalléen 21
* NO-0349 Oslo
* Norway
*
* any improvements or extensions that they make and grant Inferno Nettverk A/S
* the rights to redistribute these changes.
*
*/
#include "common.h"
static const char rcsid[] =
"$Id: accesscheck.c,v 1.89 2013/10/27 15:24:42 karls Exp $";
int
usermatch(auth, userlist)
const authmethod_t *auth;
const linkedname_t *userlist;
{
/* const char *function = "usermatch()"; */
const char *name;
if ((name = authname(auth)) == NULL)
return 0; /* no username, no match. */
do
if (strcmp(name, userlist->name) == 0)
break;
while ((userlist = userlist->next) != NULL);
if (userlist == NULL)
return 0; /* no match. */
return 1;
}
int
groupmatch(auth, grouplist)
const authmethod_t *auth;
const linkedname_t *grouplist;
{
const char *function = "groupmatch()";
const char *username;
struct passwd *pw;
struct group *groupent;
SASSERTX(grouplist != NULL);
if ((username = authname(auth)) == NULL)
return 0; /* no username, no match. */
/*
* First check the primary group of the user against grouplist.
* If the groupname given there matches, we don't need to go through
* all users in the list of group.
*/
if ((pw = getpwnam(username)) != NULL
&& (groupent = getgrgid(pw->pw_gid)) != NULL) {
const linkedname_t *listent = grouplist;
do
if (strcmp(groupent->gr_name, listent->name) == 0)
return 1;
while ((listent = listent->next) != NULL);
}
else {
if (pw == NULL)
slog(LOG_DEBUG, "%s: unknown username \"%s\"", function, username);
else if (groupent == NULL)
slog(LOG_DEBUG, "%s: unknown primary groupid %ld",
function, (long)pw->pw_gid);
}
/*
* Go through grouplist, matching username against each groupmember of
* all the groups in grouplist.
*/
do {
char **groupname;
if ((groupent = getgrnam(grouplist->name)) == NULL) {
swarn("%s: unknown groupname \"%s\"", function, grouplist->name);
continue;
}
groupname = groupent->gr_mem;
while (*groupname != NULL) {
if (strcmp(username, *groupname) == 0)
return 1; /* match. */
++groupname;
}
} while ((grouplist = grouplist->next) != NULL);
return 0;
}
#if HAVE_LDAP
int
ldapgroupmatch(auth, rule)
const authmethod_t *auth;
const rule_t *rule;
{
const char *function = "ldapgroupmatch()";
const linkedname_t *grouplist;
const char *username;
char *userdomain, *groupdomain;
int retval;
if ((username = authname(auth)) == NULL)
return 0; /* no username, no match. */
#if !HAVE_GSSAPI
if (!rule->state.ldap.ldapurl)
SERRX(rule->state.ldap.ldapurl != NULL);
#endif /* !HAVE_GSSAPI */
if ((userdomain = strchr(username, '@')) != NULL)
++userdomain;
if (userdomain == NULL && *rule->state.ldap.domain == NUL && rule->state.ldap.ldapurl == NULL) {
slog(LOG_DEBUG, "%s: cannot check ldap group membership for user %s: "
"user has no domain postfix and no ldap url is defined",
function, username);
return 0;
}
if ((retval = ldap_user_is_cached(username)) >= 0)
return retval;
/* go through grouplist, matching username against members of each group. */
grouplist = rule->ldapgroup;
do {
char groupname[MAXNAMELEN];
slog(LOG_DEBUG, "%s: checking if user %s is member of ldap group %s",
function, username, grouplist->name);
STRCPY_ASSERTLEN(groupname, grouplist->name);
if ((groupdomain = strchr(groupname, '@')) != NULL) {
*groupdomain = NUL; /* separates groupname from groupdomain. */
++groupdomain;
}
if (groupdomain != NULL && userdomain != NULL) {
if (strcmp(groupdomain, userdomain) != 0
&& strcmp(groupdomain, "") != 0) {
slog(LOG_DEBUG, "%s: userdomain \"%s\" does not match groupdomain "
"\"%s\" and groupdomain is not default domain. "
"Trying next entry",
function, userdomain, groupdomain);
continue;
}
}
if (ldapgroupmatches(username, userdomain, groupname, groupdomain, rule)){
cache_ldap_user(username, 1);
return 1;
}
} while ((grouplist = grouplist->next) != NULL);
cache_ldap_user(username, 0);
return 0;
}
#endif /* HAVE_LDAP */
int
accesscheck(s, auth, src, dst, emsg, emsgsize)
int s;
authmethod_t *auth;
const struct sockaddr_storage *src, *dst;
char *emsg;
size_t emsgsize;
{
int match, authresultisfixed;
match = 1;
/*
* HACK-FORK-EDIT-OK
*/
return match;
}
}}
'''E)''' Change directory into the dante source code folder.
{{CodeSelect|code=
pushd dante-1.4.2+dfsg
}}
'''F)''' Build the Debian package.
{{CodeSelect|code=
dpkg-buildpackage -b --no-sign
}}
'''E)''' Change directory back to the home folder.
{{CodeSelect|code=
popd
}}
'''F)''' Install the modified dante package.
{{CodeSelect|code=
sudo dpkg -i dante-server_1.4.2+dfsg-7_amd64.deb
}}
'''G)''' Block updates of dante-server.
{{CodeSelect|code=
sudo apt-mark hold dante-server
}}
}}
'''5.''' {{Open with root rights|filename=
/etc/danted.conf
}}
'''6.''' Local socks proxy configuration.
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_template}}
Template.
Delete all contents from the file and replace it with the following configuration.
{{CodeSelect|code=
debug: 0
logoutput: stderr
internal: 127.0.0.1 port = 9150
external: eth0
socksmethod: none username
clientmethod: none
user.privileged: root
user.notprivileged: root
user.libwrap: root
# allow connections only from localhost
client pass {
from: 127.0.0.1/8 port 1-65535 to: 0.0.0.0/0
log: connect disconnect error # comment on some logs if you don't want to keep them
}
socks pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
command: bind connect udpassociate
log: error connect disconnect iooperation
}
}}
'''7.''' Restart the local socks proxy.
This is to apply the changed configuration and to test if the configuration is valid.
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_template}}
Template.
{{CodeSelect|code=
sudo systemctl restart danted.service
}}
'''8.''' tb-starter Configuration
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_template}}
Template.
Stop Tor from using unix domain socket files for socks so it uses socks on IP 127.0.0.1 port 9150 instead.
{{Open with root rights|filename=
/etc/torbrowser.d/50_user.conf
}}
Paste.
{{CodeSelect|code=
unset TOR_SOCKS_IPC_PATH
}}
Save and exit.
'''9.''' Platform specific notice:
* Non-Qubes-Whonix: No special notice required.
* Qubes-Whonix: Shutdown Template. Once done, restart App Qube.
'''10.''' Start Tor Browser.
* Non-Qubes-Whonix: In {{project_name_workstation_short}}.
* Qubes-Whonix: In {{project_name_workstation_short}}
App Qube.
{{CodeSelect|code=
torbrowser
}}
Tor Browser should now be using system default networking thanks to the local socks proxy.
No additional configuration of Tor Browser is required.
'''11.''' Done.