Closed adrelanos closed 2 years ago
This command hangs as per Whonix default:
tor --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
Background:
Which command to detect the system is whonix? I will use that to not run tor.
Also, check the option -d
to debug.
One moment.
This command hangs as per Whonix default:
tor --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
Background:
I think I should fix this in Whonix.
This was simple to fix in Whonix. Fixed in Whonix. See attached commit above.
Which command to detect the system is whonix?
Good question. Just answering for academic interest. No actual related use case at the moment. Documented just now:
I will use that to not run tor.
No more need, thank you or swift response!
Solved.
https://github.com/nyxnor/tor-ctrl/issues/10#issuecomment-1013759264
the problem is that it drops -f
and --defaults-torrc
options.
That's something to be fixed in Whonix. Fixed that just now, attached commit above.
tor-ctrl -d signal NEWNYM
tor-ctrl -d signal NEWNYM
+ : signal NEWNYM
+ [ -n signal NEWNYM ]
+ printf %ssignal NEWNYM\n
+ sed s|^ ||
+ cmd_cli=signal NEWNYM
+ check_progs
+ prog_net=nc netcat socat telnet
+ has nc
+ _cmd=
+ return 1
+ has netcat
+ _cmd=
+ return 1
+ has socat
+ _cmd=/usr/bin/socat
+ [ -x /usr/bin/socat ]
+ socket_prog=socat
+ break
+ [ -z socat ]
+ : 0
+ [ -z ]
+ get_socket
+ test -f /lib/systemd/system/tor@default.service
+ grep ExecStart= /lib/systemd/system/tor@default.service
+ sed s/ExecStart=//g
+ tor_start_command=/usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
+ printf %s\n /usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
+ cut -d -f1
+ grep -- --defaults-torrc [^ ]*
+ sed s/.*--defaults-torrc //
+ default_torrc=/usr/share/tor/tor-service-defaults-torrc
+ [ -n /usr/share/tor/tor-service-defaults-torrc ]
+ printf %s\n --defaults-torrc /usr/share/tor/tor-service-defaults-torrc
+ default_torrc=--defaults-torrc /usr/share/tor/tor-service-defaults-torrc
+ printf %s\n /usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
+ cut -d -f1
+ grep -- -f [^ ]*
+ sed s/.*-f //
+ f_torrc=/etc/tor/torrc
+ [ -n /etc/tor/torrc ]
+ printf %s\n -f /etc/tor/torrc
+ f_torrc=-f /etc/tor/torrc
+ tor --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
+ sed s/"//;s/"\.//
+ awk {print $NF}
+ grep -E Read configuration file [^ ]*| Including configuration file [^ ]*
+ args=("$@")
+ true 'args: --verify-config' --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
+ file_name=
+ DataDirectory=
+ ControlSocket=
+ CookieAuthFile=
+ SocksPort=
+ socat_pid=
+ :
+ case $1 in
+ verify_config
+ /usr/bin/tor.anondist-orig --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
+ tor_config_files=/usr/share/tor/tor-service-defaults-torrc
/etc/tor/torrc
+ grep -E ^ControlPort [^ ]*|^ControlSocket [^ ]* /usr/share/tor/tor-service-defaults-torrc /etc/tor/torrc
+ head -n 1
+ sed s/"//g;s/unix\://
+ cut -d : -f2
+ cut -d -f2
+ tor_control_socket_alternative=/run/tor/control
+ tor_control_socket=/run/tor/control
+ [ -n /run/tor/control ]
+ tor_control_socket=/run/tor/control
+ get_dry_run
+ [ = 1 ]
+ check_socket
+ socket_type=unix
+ tor_control_unix=/run/tor/control
+ test -e /run/tor/control
+ test -S /run/tor/control
+ socket_prog_connect=socat UNIX-CONNECT:/run/tor/control -
+ socat UNIX-CONNECT:/run/tor/control /dev/null
+ login
+ socat UNIX-CONNECT:/run/tor/control -+ grep AUTH
+ send_cmd PROTOCOLINFO
+ printf %s\n PROTOCOLINFO
+ sleep 0
+ send_cmd QUIT
+ printf %s\n QUIT
+ sleep 0
+ auth=
+ printf %s\n
+ tr , \n
+ sed s/250-AUTH METHODS=//
+ cut -d -f1
+ auth_methods=
+ + grep -q AUTH METHODS=NULL
printf %s
+ grep ^HASHEDPASSWORD$
+ printf %s\n
+ hashedpassword_enabled=
+ tr -d \r
+ printf %s\n
+ tr -d "
+ sed s/.*COOKIEFILE=//
+ tor_cookie=
+ test -r
+ [ -n ]
+ safecookie_enabled=
+ [ -n ]
+ socat UNIX-CONNECT:/run/tor/control -
+ cmd_pipe
+ send_cmd
+ printf %s\n
+ sleep 0
+ + send_cmd signal NEWNYM
+ printf %s\n signal NEWNYM
+ sleep 0
finish
+ cat
+ [ 0 -eq 1 ]
+ send_cmd QUIT
+ printf %s\n QUIT
+ sleep 0
+ str=
+ [ 0 -eq 0 ]
+ printf %s\n
+ printf %s\n
+ grep -c ^250
+ [ 0 = 3 ]
+ exit 1
It is now passing all command line options correctly.
- /usr/bin/tor.anondist-orig --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
tor-ctrl now uses Tor control socket file /run/tor/control
which is correct. That socket is also being emulated and redirected from the workstation to onion-grater running on the gateway.
Manually in the workstation:
socat - UNIX-CONNECT:/var/run/tor/control
PROTOCOLINFO
250-PROTOCOLINFO 1
250-AUTH METHODS=NULL
250-VERSION Tor="0.4.6.9"
250 OK
tested manually on the workstation, it worked. I don't know why it is showing empty output yet.
Does tor-ctrl
have n issue with 250-AUTH METHODS=NULL
?
if printf %s"${auth}" | grep -q "AUTH METHODS=NULL"; then
printf '%s\n' "Configure an authentication method to connect to tor's controller on your torrc."
printf '%s\n' "Chose either or both options: HashedControlPassword or CookieAuthentication"
printf '%s\n' "Read the manual: https://2019.www.torproject.org/docs/tor-manual-dev.html.en"
exit 1
fi
250-AUTH METHODS=NULL
might be insecure in some setups but appropriate in others.
onion-grater
indeed replies 250-AUTH METHODS=NULL
.
https://github.com/Whonix/onion-grater/blob/master/usr/lib/onion-grater#L454
if cmd == "PROTOCOLINFO":
# Stem calls PROTOCOLINFO before authenticating. Tell the
# client that there is no authentication.
self.respond("250-PROTOCOLINFO 1")
self.respond("250-AUTH METHODS=NULL")
self.respond("250-VERSION Tor=\"{}\""
.format(self.controller.get_version()))
self.respond("250 OK")
onion-grater
permits any login method, I think. Even empty/wrong passwords. onion-grater
replies to login attempts only to stay compatible with the protocol. The login data isn't actually verified. And that's OK because which Tor control protocol commands can be executed is filtered by onion-grater
anyhow. So no security issue there.
Example from the workstation talking to onion-grater
.
socat - UNIX-CONNECT:/var/run/tor/control
signal NEWNYM
250 OK
So no login required.
hum, that might be it, I will make it accept NULL method and send string "AUTHENTICATE" without any argument.
Great!
socat - UNIX-CONNECT:/var/run/tor/control
AUTHENTICATE
250 OK
hum, that might be it, I will make it accept NULL method and send string "AUTHENTICATE" without any argument.
On a second thought, as per above output, it seems like previous code didn't catch NULL and prevent it.
Also the new commit https://github.com/nyxnor/tor-ctrl/commit/71988e5a10ffb76cb27873fbf2691aeb84ca9735 doesn't result in sending AUTHENTICATE.
user@host:~$ tor-ctrl -d signal NEWNYM
+ : signal NEWNYM
+ [ -n signal NEWNYM ]
+ printf %ssignal NEWNYM\n
+ sed s|^ ||
+ cmd_cli=signal NEWNYM
+ check_progs
+ prog_net=nc netcat socat telnet
+ has nc
+ _cmd=
+ return 1
+ has netcat
+ _cmd=
+ return 1
+ has socat
+ _cmd=/usr/bin/socat
+ [ -x /usr/bin/socat ]
+ socket_prog=socat
+ break
+ [ -z socat ]
+ : 0
+ [ -z ]
+ get_socket
+ test -f /lib/systemd/system/tor@default.service
+ grep ExecStart= /lib/systemd/system/tor@default.service
+ sed s/ExecStart=//g
+ tor_start_command=/usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
+ printf %s\n /usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
+ cut -d -f1
+ grep -- --defaults-torrc [^ ]*
+ sed s/.*--defaults-torrc //
+ default_torrc=/usr/share/tor/tor-service-defaults-torrc
+ [ -n /usr/share/tor/tor-service-defaults-torrc ]
+ printf %s\n --defaults-torrc /usr/share/tor/tor-service-defaults-torrc
+ default_torrc=--defaults-torrc /usr/share/tor/tor-service-defaults-torrc
+ printf %s\n /usr/bin/tor --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc --RunAsDaemon 0
+ cut -d -f1+ grep -- -f [^ ]*
+ sed s/.*-f //
+ f_torrc=/etc/tor/torrc
+ [ -n /etc/tor/torrc ]
+ printf %s\n -f /etc/tor/torrc
+ f_torrc=-f /etc/tor/torrc
+ tor --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
+ sed s/"//;s/".//;s/\/\//\//
+ args=("$@")
+ true 'args: --verify-config' --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
+ file_name=
+ DataDirectory=
+ ControlSocket=
+ CookieAuthFile=
+ SocksPort=
+ socat_pid=
+ :
+ case $1 in
+ verify_config
+ /usr/bin/tor.anondist-orig --verify-config --defaults-torrc /usr/share/tor/tor-service-defaults-torrc -f /etc/tor/torrc
+ + awk {print $NF}
grep -E Read configuration file [^ ]*| Including configuration file [^ ]*
+ tor_config_files=/usr/share/tor/tor-service-defaults-torrc
/etc/tor/torrc
+ grep -E ^ControlPort [^ ]*|^ControlSocket [^ ]* /usr/share/tor/tor-service-defaults-torrc /etc/tor/torrc
+ sed s/"//g;s/unix\://
+ cut -d -f2
+ cut -d : -f2
+ head -n 1
+ tor_control_socket_alternative=/run/tor/control
+ tor_control_socket=/run/tor/control
+ [ -n /run/tor/control ]
+ tor_control_socket=/run/tor/control
+ get_dry_run
+ [ = 1 ]
+ check_socket
+ socket_type=unix
+ tor_control_unix=/run/tor/control
+ test -e /run/tor/control
+ test -S /run/tor/control
+ socket_prog_connect=socat - UNIX-CONNECT:/run/tor/control
+ socat UNIX-CONNECT:/run/tor/control /dev/null
+ login
+ send_cmd PROTOCOLINFO
+ printf %s\n PROTOCOLINFO
+ sleep 0
+ socat - UNIX-CONNECT:/run/tor/control
+ grep AUTH
+ send_cmd QUIT
+ printf %s\n QUIT
+ sleep 0
+ auth=
+ printf %s\n
+ tr , \n
+ cut -d -f1
+ sed s/250-AUTH METHODS=//
+ auth_methods=
+ printf %s\n
+ tr -d \r
+ sed s/.*COOKIEFILE=//
+ tr -d "
+ tor_cookie=
+ printf %s\n
+ grep -q NULL
+ grep -q ^HASHEDPASSWORD$
+ printf %s\n
+ test -r
+ safecookie_enabled=
+ [ -n ]
+ socat - UNIX-CONNECT:/run/tor/control
+ cmd_pipe
+ send_cmd
+ printf %s\n
+ sleep 0
+ send_cmd signal NEWNYM
+ printf %s\n signal NEWNYM
+ sleep 0
+ finish
+ cat
+ [ 0 -eq 1 ]
+ send_cmd QUIT
+ printf %s\n QUIT
+ sleep 0
+ str=
+ [ 0 -eq 0 ]
+ printf %s\n
+ printf %s\n
+ grep -c ^250
+ [ 0 = 3 ]
+ exit 1
- auth=
+ login
+ send_cmd PROTOCOLINFO
+ + printf %s\nnc PROTOCOLINFO -U
/run/tor/control
+ sleep 0
+ grep AUTH
+ send_cmd QUIT
+ printf %s\n QUIT
+ sleep 0
+ auth=250-AUTH METHODS=NULL
+ printf %s\n 250-AUTH METHODS=NULL
+ sed s/250-AUTH METHODS=//
+ cut -d -f1
+ tr , \n
+ auth_methods=NULL
+ printf %s\n 250-AUTH METHODS=NULL
+ sed s/.*COOKIEFILE=//
+ tr -d+ \r
tr -d "
+ tor_cookie=250-AUTH METHODS=NULL
+ printf %s\n NULL
+ grep -q NULL
+ auth_string=AUTHENTICATE
+ safecookie_enabled=
+ [ -n ]
+ cmd_pipe
+ send_cmd AUTHENTICATE
+ printf %s\n AUTHENTICATE
+ sleep 0
+ + finish
nc -U /run/tor/control
+ cat
+ send_cmd signal newnym
+ printf %s\n signal newnym
+ sleep 0
+ [ 0 -eq 1 ]
+ send_cmd QUIT
+ printf %s\n QUIT
+ sleep 0
+ str=250 OK
250 OK
250 closing connection
+ [ 0 -eq 0 ]
+ printf %s\n 250 OK
250 OK
250 closing connection
250 OK
250 OK
250 closing connection
+ printf %s\n 250 OK
250 OK
250 closing connection
+ grep -c ^250
+ [ 3 = 3 ]
+ exit 0
it is not just not receving auth
, it is not receiving on any command.
That command is rather lengthy and complex. Hard to debug.
auth="$({ send_cmd "PROTOCOLINFO"; send_cmd "QUIT"; } | ${socket_prog_connect} 2>/dev/null | grep "AUTH")"
Can't sub-shell be avoided?
{ send_cmd "PROTOCOLINFO"; send_cmd "QUIT"; }
Is quit really required?
send_cmd "QUIT"
The 2>/dev/null
is problematic, could make debugging similar issues harder.
Would be better to split this into multiple lines? The
| grep "AUTH"
makes it impossible to see what happened earlier during the pipe even with xtrace enabled.
For debugging locally only I simplified it for now to:
auth="$(send_cmd "PROTOCOLINFO" | ${socket_prog_connect})"
I was using send_cmd there because was using file descriptors, not is is unnecessary on that part. Could be:
Can't sub-shell be avoided? Would be better to split this into multiple lines? The
protocolinfo="$(printf '%s\n%s\n' "PROTOCOLINFO" "QUIT" | ${socket_prog_connect})" auth="$(printf '%s\n' "${protocolinfo}" | grep "AUTH METHODS=")"
Is quit really required?
If something escapes to stdin, it will be sent to the connection.
I've removed a few /dev/null
and got this:
+ socket_prog_connect=socat - UNIX-CONNECT:/run/tor/control
+ socat UNIX-CONNECT:/run/tor/control
2022/01/16 18:17:07 socat[12726] E exactly 2 addresses required (there are 1); use option "-h" for help
+ error_msg socat: Connetion refused to /run/tor/control
+ printf %stor-ctrl: socat: Connetion refused to /run/tor/control\n
tor-ctrl: socat: Connetion refused to /run/tor/control
Am I onto something? Seems like somewhere still using a broken socat syntax?
Am I onto something? Seems like somewhere still using a broken socat syntax?
/dev/null there is not a redirection, it is part of socat syntax
https://stackoverflow.com/a/55359740
you can even put /dev/null in the middle to understand:
socat /dev/null UNIX-CONNECT:/run/tor/control
Indeed.
onion-grater replies but tor-ctrl does not see it. I guess what tor-ctrl is effectively doing is this:
echo PROTOCOLINFO | socat - UNIX-CONNECT:/run/tor/control
This is consistent with the onion-grater output.
Jan 16 18:28:19 host onion-grater[5250]: 10.138.21.113:58078 (filter: 30_autogenerated): -> PROTOCOLINFO
Jan 16 18:28:19 host onion-grater[5250]: 10.138.21.113:58078 (filter: 30_autogenerated): <- 250-PROTOCOLINFO 1
Jan 16 18:28:19 host onion-grater[5250]: 10.138.21.113:58078 (filter: 30_autogenerated): <- 250-AUTH METHODS=NULL
Jan 16 18:28:19 host onion-grater[5250]: 10.138.21.113:58078 (filter: 30_autogenerated) disconnected: [Errno 32] Broken pipe
socat is not working, install netcat and try it pls, maybe socat is wrong of onion-grater is filtering socat tested on workstation and got not reply from socat but got reply with netcat
On debian it works, but on whonix:
netcat shows info
printf '%s\n%s\n' "PROTOCOLINFO" "QUIT" | netcat -U /run/tor/control
printf '%s\n%s\n' "PROTOCOLINFO" "QUIT" | netcat 127.0.0.1 9051
socat shows nothing
printf '%s\n%s\n' "PROTOCOLINFO" "QUIT" | socat - UNIX-CONNECT:/run/tor/control
printf '%s\n%s\n' "PROTOCOLINFO" "QUIT" | socat - TCP:127.0.0.1:9051
but running the socat command standalone without being piped works on whonix ws:
socat - UNIX-CONNECT:/run/tor/control
-> PROTOCOLINFO
-> QUIT
I can reproduce and confirm all what you've said in your previous post.
tor-ctrl is also fixed after installing netcat.
Wondering why that is happening.
my thought: commands piped to socat are being filtered, but piped to netcat are not.
socat / netcat: onion-grater doesn't filter them. Debug output shows them as usual but with broken pipe.
Even if onion-grater would filter something there is a proper reply.
tor-ctrl invalid-command-test
250 OK 510 Command filtered 250 closing connection
will change debian/control
dependency to netcat, but if user has socat installed, it will just be used if netcat is not found.
Or I can disable socat option for whonix users inside the script, which is a workaround sadly.
Script preference seems to be netcat over socat anyhow. So, yes, once netcat is a dependency of tor-ctrl should should be good enough.
try socat with -d -d -d -d
(yes, 4 times).
Prints fatal, error, warning, notice, info, and debug messages.
this is the only way I got the protocolinfo reply with socat on whonix:
printf '%s\n%s\n' "PROTOCOLINFO" "QUIT" | socat -d -d -d -d - TCP:127.0.0.1:9051
but it does not work everytime, meaning it does not connect every time.
The socat issue was fixed by itself.
user@host:~$ tor-ctrl-stream
tor-ctrl-stream: [info]: subscribed to Tor stream events, as soon as streams are created, output will be shown below.
tor-ctrl-stream: [warn]: posting these contents online can deanonymize the tor client.
tor-ctrl: [notice] attempting to connect to tor's configuration files socket /run/tor/control
tor-ctrl: [notice] stop listening with Ctrl+C
tor-ctrl: [notice] connecting to socket with command: socat - UNIX-CONNECT:/run/tor/control
250 OK
250 OK