Commit 1684decc authored by anonym's avatar anonym
Browse files

Merge remote-tracking branch 'origin/feature/12411-tor-bootstrap-fixes' into devel

Refs: #12411
parents 6c5dc7f2 4d3ba480
......@@ -48,8 +48,7 @@ domain ip {
# White-list access to Tor's ControlPort
daddr 127.0.0.1 proto tcp dport 9052 {
# Needed by a workaround in tordate (NM's 20-time.sh hook)
# for temporarily changing Tor's logging severity.
# Needed for running the Tor control port filter
mod owner uid-owner root ACCEPT;
}
......
......@@ -6,18 +6,25 @@ TOR_DIR=/var/lib/tor
TOR_DESCRIPTORS=${TOR_DIR}/cached-microdescs
NEW_TOR_DESCRIPTORS=${TOR_DESCRIPTORS}.new
get_tor_control_port() {
sed -n 's/^ControlPort[[:space:]]\+\([[:digit:]]\+\)/\1/p' "${TOR_RC}"
get_tor_control_socket_path() {
local res
res=$(sed -n 's/^ControlSocket[[:space:]]\+\(.\+\)$/\1/p' "${TOR_RC}")
if [ "${res}" -eq 0 ]; then
echo ""
elif [ -z "${res}" ] && [ -S /var/run/tor/control ]; then
echo /var/run/tor/control
else
echo "${res}"
fi
}
tor_control_send() {
COOKIE=/var/run/tor/control.authcookie
HEXCOOKIE=$(xxd -c 32 -g 0 $COOKIE | cut -d' ' -f2)
/bin/echo -ne "AUTHENTICATE ${HEXCOOKIE}\r\n${1}\r\nQUIT\r\n" | \
nc 127.0.0.1 $(get_tor_control_port) | tr -d "\r"
socat - UNIX-CONNECT:$(get_tor_control_socket_path) | tr -d "\r"
}
# This function may be dangerous to use. See "Potential Tor bug" below.
# Only handles GETINFO keys with single-line answers
tor_control_getinfo() {
tor_control_send "GETINFO ${1}" | \
......@@ -34,28 +41,14 @@ tor_control_setconf() {
}
tor_bootstrap_progress() {
RES=$(grep -o "\[notice\] Bootstrapped [[:digit:]]\+%:" ${TOR_LOG} | \
tail -n1 | sed "s|\[notice\] Bootstrapped \([[:digit:]]\+\)%:|\1|")
if [ -z "${RES:-}" ] ; then
RES=0
fi
echo -n "$RES"
local res
res=$(tor_control_getinfo status/bootstrap-phase | \
sed 's/^.* BOOTSTRAP PROGRESS=\([[:digit:]]\+\) .*$/\1/')
echo ${res:-0}
}
# Potential Tor bug: it seems like using this version makes Tor get
# stuck at "Bootstrapped 5%" quite often. Is Tor sensitive to opening
# control ports and/or issuing "getinfo status/bootstrap-phase" during
# early bootstrap? Because of this we fallback to greping the log.
#tor_bootstrap_progress() {
# tor_control_getinfo status/bootstrap-phase | \
# sed 's/^.* BOOTSTRAP PROGRESS=\([[:digit:]]\+\) .*$/\1/'
#}
tor_is_working() {
[ -e $TOR_DESCRIPTORS ] || [ -e $NEW_TOR_DESCRIPTORS ] || return 1
TOR_BOOTSTRAP_PROGRESS=$(tor_bootstrap_progress)
[ "${TOR_BOOTSTRAP_PROGRESS:-}" -eq 100 ]
[ "$(tor_bootstrap_progress)" -eq 100 ]
}
tor_append_to_torrc () {
......
......@@ -2,7 +2,7 @@
set -e
# Import try_for() and clock_gettime_monotonic()
# Import try_for()
. /usr/local/lib/tails-shell-library/common.sh
# Import tor_bootstrap_progress()
......@@ -12,40 +12,11 @@ set -e
. /usr/local/lib/tails-shell-library/log.sh
_LOG_TAG="$(basename $0)"
# The Tor log is removed to ensure `tor_bootstrap_progress`'s output will be
# accurate.
clear_tor_log() {
rm -f /var/log/tor/log
}
clear_tor_log
systemctl restart tor@default.service
# The main point of this script is to restart Tor if bootstrapping stalls for
# more than 20 seconds
bootstrap_progress=0
last_bootstrap_change=$(clock_gettime_monotonic)
maybe_restart_tor() {
local new_bootstrap_progress=$(tor_bootstrap_progress)
if [ $new_bootstrap_progress -eq 100 ]; then
log "Tor has successfully bootstrapped."
return 0
elif [ $new_bootstrap_progress -gt $bootstrap_progress ]; then
bootstrap_progress=$new_bootstrap_progress
last_bootstrap_change=$(clock_gettime_monotonic)
return 1
elif [ $(expr $(clock_gettime_monotonic) - $last_bootstrap_change) -ge 20 ]; then
log "Tor seems to have stalled while bootstrapping. Restarting Tor."
clear_tor_log
systemctl restart tor@default.service
bootstrap_progress=0
last_bootstrap_change=$(clock_gettime_monotonic)
return 1
else
return 1
fi
}
try_for 270 maybe_restart_tor
if try_for 270 '[ "$(tor_bootstrap_progress)" -eq 100 ]'; then
log "Tor has successfully bootstrapped."
else
log "Tor failed to bootstrap"
exit 1
fi
......@@ -210,6 +210,8 @@ seahorse-daemon
seahorse-nautilus
secure-delete
simple-scan
# Tails' shell library uses socat to communicate via tor's control socket
socat
sshfs
# ships the *.c32 modules in syslinux 6.x packaging
syslinux-common
......
......@@ -70,10 +70,9 @@ def post_snapshot_restore_hook
if $vm.has_network?
if $vm.execute("systemctl --quiet is-active tor@default.service").success?
$vm.execute("systemctl stop tor@default.service")
$vm.execute("rm -f /var/log/tor/log")
$vm.execute("systemctl --no-block restart tails-tor-has-bootstrapped.target")
$vm.host_to_guest_time_sync
$vm.spawn("restart-tor")
$vm.execute("systemctl start tor@default.service")
wait_until_tor_is_working
end
else
......
......@@ -151,16 +151,13 @@ def retry_action(max_retries, options = {}, &block)
end
end
class TorBootstrapFailure < StandardError
end
def wait_until_tor_is_working
try_for(270) { $vm.execute('/usr/local/sbin/tor-has-bootstrapped').success? }
rescue Timeout::Error => e
c = $vm.execute("journalctl SYSLOG_IDENTIFIER=restart-tor")
if c.success?
debug_log("From the journal:\n" + c.stdout.sub(/^/, " "))
else
debug_log("Nothing was in the journal about 'restart-tor'")
end
raise e
rescue Timeout::Error
raise TorBootstrapFailure.new('Tor failed to bootstrap')
end
def convert_bytes_mod(unit)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment