diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b24a20
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+
+This role builds on, and requires, ../base_role and lays down the
+basics for cntlm and socks and http and https proxies. It is required
+to be run after ../base_role
+
+Look at the variables in defaults/main.yml to customize the role, and
+double-check the settings in vars/*.yml.
+
+It is multi-target and should run on Gentoo2, Debian4, Devuan5, Ubuntu18
+athough only tested on Gentoo. To bring it up to date, just copy the
+existing files in vars and maybe tasks to the new name and edit to suit,
+but be advised that it is systemd-challenged, like its author.
+
diff --git a/overlay/Linux/usr/local/bin/proxy_libvirt_ga_test.bash b/overlay/Linux/usr/local/bin/proxy_libvirt_ga_test.bash
index 7ff1bac..d6689ff 100755
--- a/overlay/Linux/usr/local/bin/proxy_libvirt_ga_test.bash
+++ b/overlay/Linux/usr/local/bin/proxy_libvirt_ga_test.bash
@@ -1,10 +1,8 @@
#!/bin/bash
ROLE=proxy
-MODE=host
#[ $# -eq 0 ] && set -- Whonix-Gateway /bin/cat /proc/cmdline
-[ $# -eq 0 ] && set -- Whonix-Gateway /bin/netstat -lnp4
[ $# -lt 2 ] && echo USAGE: $0 domain command arguments
HOST=$1
diff --git a/overlay/Linux/usr/local/bin/proxy_ping_test.bash b/overlay/Linux/usr/local/bin/proxy_ping_test.bash
index f0fa7d4..b4c2195 100755
--- a/overlay/Linux/usr/local/bin/proxy_ping_test.bash
+++ b/overlay/Linux/usr/local/bin/proxy_ping_test.bash
@@ -7,6 +7,7 @@ ROLE=proxy
PYVER=3
# DEBUG=1
+# TRACE=1
. /usr/local/bin/proxy_ping_lib.bash || \
{ ERROR loading /usr/local/bin/proxy_ping_lib.bash ; exit 6; }
@@ -19,17 +20,17 @@ which nslookup 2>/dev/null >/dev/null && HAVE_NSLOOKUP=1 || HAVE_NSLOOKUP=0
which tor-resolve 2>/dev/null >/dev/null && HAVE_TOR_RESOLVE=1 || HAVE_TOR_RESOLVE=0
[ -z "$prog" ] || prog=proxy_ping_test
-proxy_ping_get_socks
+proxy_ping_get_socks >/dev/null
[ -z "$SOCKS_HOST" ] && SOCKS_HOST=127.0.0.1
[ -z "$SOCKS_PORT" ] && SOCKS_PORT=9050
[ -z "$SOCKS_DNS" ] && SOCKS_DNS=9053
HTTPS_PORT=9128
HTTPS_HOST=127.0.0.1
-proxy_ping_get_https
+proxy_ping_get_https >/dev/null
[ -z "$HTTPS_HOST" ] && HTTPS_HOST=127.0.0.1
HTTP_PORT=3128
HTTP_PROXY_HOST=127.0.0.1
-proxy_ping_get_http
+proxy_ping_get_http >/dev/null
[ -z "$HTTP_HOST" ] && HTTP_HOST=127.0.0.1
[ -f $PREFIX/etc/testforge/testforge.bash ] && \
@@ -80,9 +81,15 @@ SCURL="/usr/local/bin/scurl.bash --output /dev/null"
NSL='nslookup -querytype=A -debug'
NETS='netstat -nl4e'
ALL=""
+USAGE="$prog without arguments tests the current MODE=$MODE,
+or with 0 to list the tests by number,
+or one or more of the groups:
+
+"
[ -z "$USER" ] && USER=$(id -un )
-[ $USER = root ] && DMESG_LINES=1 || DMESG_LINES=0
+[ $USER = root -a -n "$TRACE" -a "$TRACE" != '0' ] && DMESG_LINES=1 || DMESG_LINES=0
+
[ -n "$PROXY_WLAN" ] || PROXY_WLAN=`proxy_ping_get_wlan`
# fixme - required
PROXY_WLAN=$( echo $PROXY_WLAN | grep ^wlan |sed -e 's/:.*//' )
@@ -91,11 +98,6 @@ PROXY_WLAN=$( echo $PROXY_WLAN | grep ^wlan |sed -e 's/:.*//' )
# fixme - required
PROXY_WLAN_GW=$( echo $PROXY_WLAN_GW | grep ^wlan |sed -e 's/:.*//' )
MODE=$( proxy_ping_mode )
-USAGE="$prog without arguments tests the current MODE=$MODE,
-or 0 to list the tests by number,
-or one or more of the groups:
-
-"
DNS_HOST=$SOCKS_HOST
[ -z "$PRIV_BIN_OWNER" ] && PRIV_BIN_OWNER=bin
@@ -244,20 +246,21 @@ proxy_run_as_root () { DBUG proxy_run_as_root $* ;
return 1
}
-## proxy_test_pretests
-proxy_test_pretests () {
- if [ "$1" = panic ] ; then
+# could pull these out as tests and add them to
+## proxy_test_pretest_exit
+proxy_test_pretest_exit () {
+ proxy_route_test || { ERROR $prog route not connected ; exit 1$? ; }
+ if [ "$1" = panic -o "$1" = firewall ] ; then
: dont ping on panic
proxy_ping_broken || proxy_do_ping || \
{ WARN ping failed for panic so skipping ; exit 0 ; }
elif [ "$1" = direct -o "$1" = gateway -o "$1" = vda -o "$1" = kick ] ; then
- proxy_route_test || { ERROR $prog route not connected ; exit 1$? ; }
proxy_ping_broken || proxy_do_ping || exit 3$?
proxy_ping_test_resolv $MODE ||\
{ WARN $prog proxy_ping_test_resolv=$? 'echo nameserver 127.0.0.1 > /etc/resolv.conf' ; exit 4 ; }
proxy_ping_firewall_start || { ERROR "proxy_ping_firewall_start ret=$?" ; exit 5 ; }
elif [ "$1" = nat ] ; then
- proxy_route_test || { ERROR $prog route not connected ; exit 1$? ; }
+ : proxy_route_test || { ERROR $prog route not connected ; exit 1$? ; }
else
proxy_do_ping || exit 4$?
proxy_ping_test_resolv $MODE || \
@@ -270,9 +273,25 @@ proxy_test_pretests () {
## proxy_test_help_args
proxy_test_help_args () {
+ declare -a elts=()
declare -a ret=()
- ret=( $(grep " -.* $1 " /tmp/proxy_ping_test.hlp | \
- sed -e 's/.=.*//' -e 's/.*tests.//') )
+ local elt
+ if [ "$1" = selektor -o "$1" = whonix -o "$1" = torhost ] ; then
+ elts=($1 socks http dns https tordns firefail)
+ elif [ "$1" = torlibvirthost ] ; then
+ elts=($1 libvirthost socks http https tordns firefail)
+ elts+=($MODE)
+ elif [ "$1" = gateway ] ; then
+ elts=($1 libvirtguest socks dns http https firefail)
+ else
+ elts=($1)
+ fi
+ for elt in "${elts[@]}" ; do
+# DBUG proxy_test_help_args $elt $1 >&2
+ ret+=( $(grep " -.* $elt " /tmp/proxy_ping_test.hlp | \
+ sed -e 's/.=.*//' -e 's/.*tests.//') )
+ done
+ DBUG proxy_test_help_args "${ret[@]}" >&2
echo "${ret[@]}"
return 0
}
@@ -293,9 +312,6 @@ proxy_ping_test_set_args () {
## vda - through the Gateway with the firewall - also polipo,panic - uses env
[ "$1" = vda ] &&
aret=( 35 3 20 ) #
-## tor - tor with the firewall to test the host side tor server - call to_tor,dns,ntp in addition
-[ "$1" = tor ] &&
- aret=( 21 30 20 4 5 36 3 )
## kick - open firewall with tor running - call dns,polipo +tor in addition
[ "$1" = kick -o "$1" = host ] &&
aret=( 24 31 13 16 6 )# 30 24 31 6 13 16
@@ -304,15 +320,19 @@ proxy_ping_test_set_args () {
aret=( 23 25 4 5 30 24 17 3 21 ) # 31 6 16
# aliases
+# socks defines http as the target of a user using socks
[ "$1" = "$SOCKS_PORT" ] && set -- socks
+# http defines http as the target of a user using http
[ "$1" = "$HTTP_PORT" ] && set -- http
+# https defines http as the target of a user using https
[ "$1" = "$HTTPS_PORT" ] && set -- https
+# dns defines http as the target of a user using dns
[ "$1" = "53" ] && set -- dns
+# tordns defines http as the target of a user using tordns
[ "$1" = "9053" ] && set -- tordns
[ "$1" = scan ] && set -- iwlist
[ "$1" = panic ] && set -- firewall
-[ "$1" = tor ] && set -- torhost
[ "$1" = to_gateway ] && set -- whonix
[ "$1" = from_tor ] && set -- whonix
[ "$1" = from_gateway ] && set -- gateway
@@ -326,11 +346,11 @@ proxy_ping_test_set_args () {
set -- ping dns socks http https tordns firefail libvirtguest
# wifi?
[ "$1" = whonix ] && \
- set -- ping tordns dns socks http https torhost tordns firefail gw
-[ "$1" = tor ] && \
- set -- ping tordns dns trace socks http https torhost tordns firefail nmap gw
-[ "$1" = selektor ] && \
- set -- ping tordns dns trace socks http https torhost tordns firefail nmap gw
+ set -- ping tordns dns socks http https torhost tordns firefail gw
+[ "$1" = tor -o "$1" = selektor ] && \
+ set -- ping tordns dns trace torhost nmap gw
+## torhost implies -
+#? tor with the firewall to test the host side tor server - call to_tor,dns,ntp in addition
[ "$1" = direct -o "$1" = '' ] && \
set -- ping dns trace nmap gw
@@ -339,33 +359,34 @@ proxy_ping_test_set_args () {
# aret="${#tests[@]}"
## gw - test if we are connected to the gateway
-## torhost - running tor with the firewall
## env - from the cmdline with a properly setup env
## firefail - test the proxy without env vars to expect failure
+## torhost - running tor with the firewall
## http - assumes torhost or whonix and env setup
## https - assumes torhost or whonix and env setup
## socks - assumes torhost or whonix and env setup
+## tordns - test 9053 for dns using tor-resolve
+## dns - dns using tor or the gateway, with the firewall - does not assume env
## ping - connected routed test the ping to DNS hosts
## ntp - ntpdate through the firewall
## nmap - nmap sgid through the firewall - does not assume env
-## iwlist - wlan scan
+## iwlist - wlan scan of a wifi host
## firewall - test that the firewall blocks
-## virbr1 - assumes tor or whonix
-## gateway - ssh to the whonix gateway
+## virbr1 - looks for virbr1 on a libvirt host torhost or whonix
+## gateway - ssh to the whonix gateway from the torhost
## trace - traceroute to DNSHOST - icmp is allowed by the firewall, except on vda
## wifi - test if we are connected - call scan in addition
## libvirthost - hosting a libvirt container
## libvirtguest - in a libvirt container
-## tordns - test 9053 for dns using tor-resolve
-## dns - dns using tor or the gateway, with the firewall - does not assume env
-## whonix - whonix to the Gateway with the firewall - also panic - not assume env
-## whonix - whonix gateway host side client setup with the firewall was from_to## direct - assume no firewall and no proxy - but may work depend on env
-r
+## whonix - whonix torhost with libvirt container running gateway behind firewall - aliases: to_gateway from_tor
+## direct - assume no firewall and no proxy - but may work depend on env
+
for elt in "$@" ; do
if [ "$elt" = gw -o "$elt" = '' -o "$elt" = env -o \
"$elt" = https -o "$elt" = http -o "$elt" = socks -o "$elt" = dns -o \
"$elt" = torhost -o "$elt" = tordns -o "$elt" = whonix -o \
- "$elt" = libvirthost -o "$elt" = libvirtguest -o "$elt" = virbr1 -o \
+ "$elt" = libvirthost -o "$elt" = torlibvirthost -o \
+ "$elt" = libvirtguest -o "$elt" = virbr1 -o \
"$elt" = ping -o "$elt" = trace -o "$elt" = ntp -o "$elt" = nmap -o \
"$elt" = iwlist -o "$elt" = firefail -o "$elt" = direct -o \
"$elt" = trace -o "$elt" = wifi -o "$elt" = '' -o "$elt" = '' \
@@ -405,9 +426,8 @@ if [ $1 = '-h' -o $1 = '--help' ] ; then
set -- `proxy_ping_test_set_args "$@"`
DBUG running tests numbered "$@"
fi
-proxy_route_test || { ERROR $prog route not connected ; exit 1$? ; }
-proxy_test_pretests "$1"
+proxy_test_pretest_exit "$1"
# https://stackoverflow.com/questions/8290046/icmp-sockets-linux/20105379#20105379
if [ $( id -u ) -eq 0 ] ; then
@@ -471,6 +491,7 @@ while [ "$#" -gt 0 ] ; do
[ $DEBIAN -eq 0 ] && continue
[ -z "$socks_proxy" ] && socks_proxy=socks5h://${SOCKS_HOST}:$SOCKS_PORT
+ # mode whonix implies torhost
if [ $MODE = whonix ] ; then
ssh -o ForwardX11=no user@10.0.2.15 netstat -nl4e| grep 15:$SOCKS_PORT || {
retval=$?
@@ -496,14 +517,16 @@ while [ "$#" -gt 0 ] ; do
GREP="$SOCKS_PORT"
elif [ $ARG -eq 4 ] ; then
- tests[4]="dig_socks_through_as_user @${SOCKS_HOST} -p $SOCKS_DNS www.whatismypublicip.com - tordns "
+ tests[4]="dig_socks_through_as_user @${SOCKS_HOST} -p $SOCKS_DNS $DNS_TARGET - tordns "
[ $HAVE_DIG = 1 ] || continue
if [ $MODE = whonix ] ; then
+ # test ssh to the whonix_gateway libvirt container
+ # and make sure that the socks proxy is runninh
ssh -o ForwardX11=no user@10.0.2.15 netstat -nl4e | grep 15:$SOCKS_DNS
fi
- dig @${SOCKS_HOST} -p $SOCKS_DNS www.whatismypublicip.com +timeout=$TIMEOUT >/dev/null || { \
+ dig @${SOCKS_HOST} -p $SOCKS_DNS $DNS_TARGET +timeout=$TIMEOUT >/dev/null || { \
retval=$?
- WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval dig @${SOCKS_HOST} -p $SOCKS_DNS www.whatismypublicip.com
+ WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval dig @${SOCKS_HOST} -p $SOCKS_DNS $DNS_TARGET
[ -z "$ALL" ] && exit $ARG$retval || continue
}
INFO $prog test=$ARG "${tests[$ARG]}"
@@ -513,7 +536,7 @@ while [ "$#" -gt 0 ] ; do
elif [ $ARG -eq 5 ] ; then
tests[5]="nslookup_socks_as_user - tordns "
[ $HAVE_NSLOOKUP = 1 ] || continue
- desc="$NSL -port=$SOCKS_DNS www.whatismypublicip.com ${DNS_HOST}"
+ desc="$NSL -port=$SOCKS_DNS $DNS_TARGET ${DNS_HOST}"
$desc >/dev/null || { \
retval=$?
WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval $desc
@@ -697,8 +720,9 @@ while [ "$#" -gt 0 ] ; do
[ $DEBIAN -eq 0 ] && continue
socks_proxy=socks5h://${SOCKS_HOST}:$SOCKS_PORT
- proxy_ping_curl -x $socks_proxy https://$HTTP_TARGET >/dev/null \
- || { retval=$? ; ERROR $prog test=$ARG "${tests[$ARG]}" retval=$retval curl $SOCKS_PORT
+ proxy_ping_curl -x $socks_proxy https://$HTTP_TARGET >/dev/null || {
+ retval=$? ;
+ ERROR $prog test=$ARG "${tests[$ARG]}" retval=$retval curl $SOCKS_PORT
[ -z "$ALL" ] && exit $ARG$retval || continue
}
INFO $prog test=$ARG "${tests[$ARG]}"
@@ -742,11 +766,11 @@ while [ "$#" -gt 0 ] ; do
INFO $prog test=$ARG "${tests[$ARG]}"
elif [ $ARG -eq 24 ] ; then
- tests[24]="dig_direct_or_dnsmasq dig -b $IP www.whatismypublicip.com - direct "
+ tests[24]="dig_direct_or_dnsmasq dig -b $IP $DNS_TARGET - direct "
[ $HAVE_DIG = 1 ] || continue
[ -n "$PROXY_WLAN" -a -n "$IP" ] || proxy_ping_get_wlan_gw || continue
[ -n "$IP" ] || continue
- dig -b $IP www.whatismypublicip.com +timeout=$TIMEOUT >/dev/null || { \
+ dig -b $IP $DNS_TARGET +timeout=$TIMEOUT >/dev/null || { \
retval=$?
WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval dig -b $IP
[ -z "$ALL" ] && exit $ARG$retval || continue
@@ -758,9 +782,9 @@ while [ "$#" -gt 0 ] ; do
[ $HAVE_NSLOOKUP = 1 ] || continue
# noenv with or without proxy
# @$DNS_HOST1 should fail for firewall unless dnsmasq is working
- $NSL >/dev/null www.whatismypublicip.com || { \
+ $NSL >/dev/null $DNS_TARGET || { \
retval=$?
- WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval nslookup www.whatismypublicip.com
+ WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval nslookup $DNS_TARGET
[ -z "$ALL" ] && exit $ARG$retval || continue
}
INFO $prog test=$ARG "${tests[$ARG]}" nslookup
@@ -768,7 +792,7 @@ while [ "$#" -gt 0 ] ; do
elif [ $ARG -eq 26 ] ; then
tests[26]="route_connected_ping_scan - direct "
[ $HAVE_DIG = 1 ] || continue
- #? proxy_test_pretests
+ #? done already in proxy_test_pretest_exit
proxy_do_ping && \
INFO $prog test=$ARG "${tests[$ARG]}" retval=$retval dig -b $IP || \
WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval dig -b $IP
@@ -777,7 +801,7 @@ while [ "$#" -gt 0 ] ; do
tests[27]="dns_as_user dig -b 127.0.0.1 - direct "
[ $HAVE_DIG = 1 ] || continue
[ -n "$PROXY_WLAN" -a -n "$IP" ] || proxy_ping_get_wlan_gw || continue
- dig -b 127.0.0.1 www.whatismypublicip.com +timeout=$TIMEOUT >/dev/null || { \
+ dig -b 127.0.0.1 $DNS_TARGET +timeout=$TIMEOUT >/dev/null || { \
retval=$?
WARN $prog test=$ARG "${tests[$ARG]}" retval=$retval dig -b $IP
[ -z "$ALL" ] && exit $ARG$retval || continue
@@ -808,9 +832,9 @@ while [ "$#" -gt 0 ] ; do
elif [ $ARG -eq 30 ] ; then
tests[30]="tor_bootstrap_check_as_root tor_bootstrap_check.py - torhost "
- [ $MODE = tor -o $MODE = selektor ] || {
- ERROR $prog MODE != tor test=$ARG
- [ -z "$ALL" ] && exit $ARG$retval || continue
+ [ $MODE = tor -o $MODE = whonix -o $MODE = selektor ] || {
+ # are there other roles that run tor?
+ WARN $prog MODE != tor test=$ARG
}
port=$SOCKS_PORT
$NETS | grep -q :$port || {
@@ -834,7 +858,7 @@ while [ "$#" -gt 0 ] ; do
tests[31]="curl_noproxy_as_root polipo http pages $HTTP_PORT - direct http "
proxy_ping_curl --noproxy http://${HTTP_HOST}:$HTTP_PORT && { \
retval=$?
- ERROR PANIC: $prog test=$ARG "${tests[$ARG]}" retval=$retval polipo http pages $HTTP_PORT
+ ERROR PANIC: $prog test=$ARG "${tests[$ARG]}" retval=$retval http to $HTTP_PORT
[ -z "$ALL" ] && exit $ARG$retval || continue
}
INFO $prog test=$ARG "${tests[$ARG]}"
@@ -923,7 +947,7 @@ while [ "$#" -gt 0 ] ; do
INFO $prog test=$ARG "${tests[$ARG]}"
GREP=""
elif [ $ARG -eq 38 ] ; then
- tests[38]="qemu-guest-agent and ports - libvirthost whonix "
+ tests[38]="qemu-guest-agent and ports - libvirthost "
[ $USER = root ] || continue
$PL proxy_libvirt_list
aret=$?
@@ -932,9 +956,10 @@ while [ "$#" -gt 0 ] ; do
elif [ $aret -ne 10 -a $aret -ne 0 ] ; then
DBUG proxy_libvirt_status aret=$aret
else
- $PL proxy_libvirt_list | grep -q "$GATEW_DOM" || {
- ERROR MODE=$MODE and $GATEW_DOM not running ;
- [ -z "$ALL" ] && exit $ARG$retval || continue
+ # was $GATEW_DOM but now can be gentoo_vm-2 etc
+ $PL proxy_libvirt_list 2>&1 | grep -q "running" || {
+ WARN MODE=$MODE and nothing libvirt running ;
+ continue
}
INFO $prog test=$ARG "${tests[$ARG]}"
fi
@@ -959,8 +984,6 @@ exit 0
curl $D -k --proxy
3)
curl $D -k --proxy socks5://${SOCKS_HOST}:$SOCKS_PORT --proxy-insecure
- 5)
- nslookup -port=$SOCKS_DNS www.whatismypublicip.com ${SOCKS_HOST} \
6)
curl -k --proxy $HTTP_PORT
16)
diff --git a/overlay/Linux/usr/local/etc/ssl/cacert-testforge.pem b/overlay/Linux/usr/local/etc/ssl/cacert-testforge.pem
new file mode 120000
index 0000000..169da01
--- /dev/null
+++ b/overlay/Linux/usr/local/etc/ssl/cacert-testforge.pem
@@ -0,0 +1 @@
+cacert-curl.se_ca_cacert.pem
\ No newline at end of file
diff --git a/overlay/Linux/usr/local/etc/systemd/KickSecure.mask b/overlay/Linux/usr/local/etc/systemd/KickSecure.mask
new file mode 100755
index 0000000..b308633
--- /dev/null
+++ b/overlay/Linux/usr/local/etc/systemd/KickSecure.mask
@@ -0,0 +1,285 @@
+# accounts-daemon.service
+# acpid.path
+# acpid.service
+# acpid.socket
+# acpi-support.service
+# alsa-restore.service
+# alsa-state.service
+# alsa-utils.service
+# apparmor.service
+# apparmor.service.d
+apt-daily.service
+apt-daily.timer
+apt-daily-upgrade.service
+apt-daily-upgrade.timer
+# autovt@.service
+# basic.target
+# blk-availability.service
+# blockdev@.target
+bluetooth.target
+# bootclockrandomization.service
+# boot-complete.target
+# canary.service
+# console-getty.service
+# console-setup.service
+# console-setup.service.d
+# container-getty@.service
+# cryptdisks-early.service
+# cryptdisks.service
+# cryptsetup-pre.target
+# cryptsetup.target
+# ctrl-alt-del.target
+# dbus-org.freedesktop.hostname1.service
+# dbus-org.freedesktop.locale1.service
+# dbus-org.freedesktop.login1.service
+# dbus-org.freedesktop.timedate1.service
+# dbus.service
+# dbus.socket
+# debug-shell.service
+# default.target
+dev-hugepages.mount
+# dev-mqueue.mount
+# dist-skel-first-boot.service
+# dm-event.service
+# dm-event.socket
+# e2scrub_all.service
+# e2scrub_all.timer
+# e2scrub_fail@.service
+# e2scrub_reap.service
+# e2scrub@.service
+# emergency.service
+# emergency.target
+# exit.target
+# final.target
+# first-boot-complete.target
+# flatpak-system-helper.service
+# fstrim.service
+# fstrim.timer
+# gdm3.service
+# gdm.service
+# getty-pre.target
+# getty@.service
+# getty-static.service
+# getty.target
+# getty.target.wants
+# graphical.target
+# graphical.target.wants
+# halt.target
+# haveged.service
+# haveged.service.d
+# hibernate.target
+# hide-hardware-info.service
+# hwclock.service
+# hybrid-sleep.target
+# initrd-cleanup.service
+# initrd-fs.target
+# initrd-parse-etc.service
+# initrd-root-device.target
+# initrd-root-device.target.wants
+# initrd-root-fs.target
+# initrd-switch-root.service
+# initrd-switch-root.target
+# initrd.target
+# initrd-udevadm-cleanup-db.service
+# jitterentropy.service
+# kexec.target
+# keyboard-setup.service
+# kmod.service
+# kmod-static-nodes.service
+# live-mode-apparmor.service
+# live-tools.service
+# local-fs-pre.target
+# local-fs.target
+# local-fs.target.wants
+# lvm2-lvmpolld.service
+# lvm2-lvmpolld.socket
+# lvm2-monitor.service
+# lvm2-pvscan@.service
+# lvm2.service
+# machine.slice
+# man-db.service
+# man-db.timer
+# mnt-shared-kvm.service
+# mnt-shared-vbox.service
+# modprobe@.service
+# msgcollector.service
+# multi-user.target
+# multi-user.target.wants
+# NetworkManager-dispatcher.service
+# NetworkManager.service
+# NetworkManager-wait-online.service
+# network-online.target
+# network-pre.target
+# network.target
+# nss-lookup.target
+# nss-user-lookup.target
+# openvpn-client@.service
+# openvpn@openvpn.service.d
+# openvpn-server@.service
+# openvpn.service
+# openvpn@.service
+# orca-kill-at-shutdown.service
+# paths.target
+# permission-hardening.service
+# polkit.service
+# poweroff.target
+# printer.target
+# proc-hidepid.service
+# procps.service
+# proc-sys-fs-binfmt_misc.automount
+# proc-sys-fs-binfmt_misc.mount
+# pulseaudio-enable-autospawn.service
+# qubes-sync-time.service.d
+# quotaon.service
+# rc-local.service
+# rc-local.service.d
+# rc.service
+# rcS.service
+# reboot.target
+# remote-cryptsetup.target
+# remote-fs-pre.target
+# remote-fs.target
+# remount-secure.service
+# remove-system-map.service
+# rescue.service
+# rescue.target
+# rescue.target.wants
+# rpcbind.target
+# rsync.service
+# runlevel0.target
+# runlevel1.target
+# runlevel1.target.wants
+# runlevel2.target
+# runlevel2.target.wants
+# runlevel3.target
+# runlevel3.target.wants
+# runlevel4.target
+# runlevel4.target.wants
+# runlevel5.target
+# runlevel5.target.wants
+# runlevel6.target
+sdwdate-gui-shutdown-notify.service
+sdwdate-pre.service
+sdwdate.service
+# sdwdate.service.d
+sdwdate-start-anondate-set-file-watcher.service
+# serial-getty@.service
+# shutdown.target
+# sigpwr.target
+# sleep.target
+# slices.target
+# smartcard.target
+# sockets.target
+# sockets.target.wants
+# sound.target
+# sound.target.wants
+# sudo.service
+# suspend.target
+# suspend-then-hibernate.target
+# swap.target
+# sys-fs-fuse-connections.mount
+# sysinit.target
+# sysinit.target.wants
+# sys-kernel-config.mount
+# sys-kernel-debug.mount
+# sys-kernel-tracing.mount
+# syslog.socket
+# systemd-ask-password-console.path
+# systemd-ask-password-console.service
+# systemd-ask-password-wall.path
+# systemd-ask-password-wall.service
+# systemd-backlight@.service
+# systemd-binfmt.service
+# systemd-bless-boot.service
+# systemd-boot-check-no-failures.service
+# systemd-boot-system-token.service
+# systemd-exit.service
+# systemd-fsckd.service
+# systemd-fsckd.socket
+# systemd-fsck-root.service
+# systemd-fsck@.service
+# systemd-halt.service
+# systemd-hibernate-resume@.service
+# systemd-hibernate.service
+# systemd-hostnamed.service
+# systemd-hwdb-update.service
+# systemd-hybrid-sleep.service
+# systemd-initctl.service
+# systemd-initctl.socket
+# systemd-journald-audit.socket
+# systemd-journald-dev-log.socket
+# systemd-journald.service
+# systemd-journald@.service
+# systemd-journald.socket
+# systemd-journald@.socket
+# systemd-journald-varlink@.socket
+# systemd-journal-flush.service
+# systemd-kexec.service
+# systemd-localed.service
+# systemd-localed.service.d
+# systemd-logind.service
+# systemd-machine-id-commit.service
+# systemd-modules-load.service
+# systemd-networkd.service
+# systemd-networkd.socket
+# systemd-networkd-wait-online.service
+# systemd-network-generator.service
+# systemd-poweroff.service
+# systemd-pstore.service
+# systemd-quotacheck.service
+# systemd-random-seed.service
+# systemd-reboot.service
+# systemd-remount-fs.service
+# systemd-resolved.service
+# systemd-resolved.service.d
+# systemd-rfkill.service
+# systemd-rfkill.socket
+# systemd-suspend.service
+# systemd-suspend-then-hibernate.service
+# systemd-sysctl.service
+# systemd-sysusers.service
+# systemd-timedated.service
+# systemd-timesyncd.service.d
+# systemd-time-wait-sync.service
+# systemd-tmpfiles-clean.service
+# systemd-tmpfiles-clean.timer
+# systemd-tmpfiles-setup-dev.service
+# systemd-tmpfiles-setup.service
+# systemd-udevd-control.socket
+# systemd-udevd-kernel.socket
+# systemd-udevd.service
+# systemd-udev-settle.service
+# systemd-udev-trigger.service
+# systemd-update-utmp-runlevel.service
+# systemd-update-utmp.service
+# systemd-user-sessions.service
+# systemd-volatile-root.service
+# system-systemd\x2dcryptsetup.slice
+# system-update-cleanup.service
+# system-update-pre.target
+# system-update.target
+# timers.target
+# timers.target.wants
+# timesanitycheck.service
+# time-set.target
+# time-sync.target
+# tor@default.service
+tor.service
+tor@.service
+# udev.service
+# udisks2.service
+# umount.target
+# upower.service
+# usb-gadget.target
+# user-runtime-dir@.service
+# user@.service
+# user@.service.d
+# user.slice
+# user-.slice.d
+# virtualbox-guest-utils.service
+# whonix-legacy.service
+# wpa_supplicant-nl80211@.service
+# wpa_supplicant.service
+# wpa_supplicant@.service
+# wpa_supplicant-wired@.service
+# x11-common.service
diff --git a/overlay/Linux/usr/local/etc/systemd/proxy.mask b/overlay/Linux/usr/local/etc/systemd/proxy.mask
new file mode 100644
index 0000000..11d08a8
--- /dev/null
+++ b/overlay/Linux/usr/local/etc/systemd/proxy.mask
@@ -0,0 +1,7 @@
+multi-user.target.wants/NetworkManager.service
+multi-user.target.wants/bootclockrandomization.service
+multi-user.target.wants/openvpn.service
+multi-user.target.wants/remote-fs.target
+multi-user.target.wants/sdwdate.service
+privoxy.service
+sdwdate.service
diff --git a/overlay/Linux/usr/local/lib/whonix-libvirt/host-boot-popup b/overlay/Linux/usr/local/lib/whonix-libvirt/host-boot-popup
new file mode 100755
index 0000000..ce2d360
--- /dev/null
+++ b/overlay/Linux/usr/local/lib/whonix-libvirt/host-boot-popup
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+## Copyright (C) 2020 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## https://forums.whonix.org/t/whonix-host-operating-system/3931/236
+
+title="WARNING - Whonix-Host DEVELOPERS-ONLY Preview Version"
+
+text="\
+
+DO NOT USE THIS YET AS A USER!
+
+Whonix-Host is unreleased. Not even available for testers. This version is a preview for developers only.
+
+Missing features the the initial release include
+
+
+
+
+See full task list for first release of Whonix-Host.
+
+Help welcome!
+
+"
+
+[ -d ~/.config/whonix/host-boot-popup ] || mkdir -p ~/.config/whonix/host-boot-popup
+[ -z "$DISPLAY" ] || \
+ [ -f /usr/lib/msgcollector/one-time-popup ] || \
+ /usr/lib/msgcollector/one-time-popup ~/.config/whonix/host-boot-popup/dismissed_version_1 "$title" "$text"
diff --git a/overlay/Linux/usr/local/lib/whonix-libvirt/host-boot-popup.dst b/overlay/Linux/usr/local/lib/whonix-libvirt/host-boot-popup.dst
new file mode 100755
index 0000000..3a75895
--- /dev/null
+++ b/overlay/Linux/usr/local/lib/whonix-libvirt/host-boot-popup.dst
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+## Copyright (C) 2020 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## https://forums.whonix.org/t/whonix-host-operating-system/3931/236
+
+title="WARNING - Whonix-Host DEVELOPERS-ONLY Preview Version"
+
+text="\
+
+DO NOT USE THIS YET AS A USER!
+
+Whonix-Host is unreleased. Not even available for testers. This version is a preview for developers only.
+
+Missing features the the initial release include
+
+
+
+See full task list for first release of Whonix-Host.
+
+Help welcome!
+
+"
+
+mkdir -p ~/.config/whonix/host-boot-popup
+/usr/lib/msgcollector/one-time-popup ~/.config/whonix/host-boot-popup/dismissed_version_1 "$title" "$text"
diff --git a/overlay/Linux/usr/local/lib/whonix-libvirt/install b/overlay/Linux/usr/local/lib/whonix-libvirt/install
new file mode 100755
index 0000000..11fb4bb
--- /dev/null
+++ b/overlay/Linux/usr/local/lib/whonix-libvirt/install
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+[ -f /var/lib/whonix-libvirt/install.done ] && exit 0
+
+## Copyright (C) 2019 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -x
+set -e
+
+## {{ Taken from qemu-system-common.postinst.
+# Add the kvm group unless it's already there
+if ! getent group kvm >/dev/null; then
+ addgroup --quiet --system kvm || true
+fi
+## }} Taken from qemu-system-common.postinst.
+
+## {{ Taken from libvirt-bin.postinst.
+if ! getent group libvirt >/dev/null; then
+ addgroup --system libvirt
+fi
+## }} Taken from libvirt-bin.postinst.
+
+## Existence of user "user" is not guaranteed at this point.
+## XXX: Or is it?
+grep -q ^kvm /etc/group || addgroup user kvm
+grep -q ^libvirt /etc/group || addgroup user libvirt
+
+## Create shared directory and adjust permissions
+[ -d /mnt/gateway-shared ] || mkdir --parents /mnt/gateway-shared
+[ -d /mnt/workstation-shared ] || mkdir --parents /mnt/workstation-shared
+chmod 1777 /mnt/gateway-shared
+chmod 1777 /mnt/workstation-shared
+
+## TODO: proper error handling. '|| true' can probably be removed.
+
+virsh -c qemu:///system net-autostart "default" || true
+virsh -c qemu:///system net-start "default" || true
+virsh -c qemu:///system net-define "/usr/local/share/whonix-libvirt/xml/Whonix-External.xml" || true
+virsh -c qemu:///system net-define "/usr/local/share/whonix-libvirt/xml/Whonix-Internal.xml" || true
+virsh -c qemu:///system net-autostart "Whonix-External" || true
+virsh -c qemu:///system net-start "Whonix-External" || true
+virsh -c qemu:///system net-autostart "Whonix-Internal" || true
+virsh -c qemu:///system net-start "Whonix-Internal" || true
+
+## Doing the following in a temporary directory to avoid modified files should
+## this be interrupted in the middle.
+temp_dir="$(mktemp --directory)"
+cp -r /usr/local/share/whonix-libvirt/xml "$temp_dir"
+
+if virsh capabilities | grep "" ; then
+ true "OK: found KVM"
+else
+ ## replace the 'kvm' domain type with 'qemu'
+ search=""
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+
+ search=""
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+
+ ## https://forums.whonix.org/t/whonix-host-operating-system/3931/251
+ search=""
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+
+ ## https://forums.whonix.org/t/whonix-host-operating-system/3931/284
+ search="1"
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+
+ ## https://forums.whonix.org/t/whonix-host-operating-system/3931/284
+ search="1"
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+fi
+
+test -f "$temp_dir/xml/Whonix-Gateway.xml"
+test -f "$temp_dir/xml/Whonix-Workstation.xml"
+
+virsh -c qemu:///system define "$temp_dir/xml/Whonix-Gateway.xml" || true
+virsh -c qemu:///system define "$temp_dir/xml/Whonix-Workstation.xml" || true
+
+virt-xml "Whonix-Gateway" --add-device --filesystem source=/mnt/gateway-shared,target=shared,type=mount,accessmode=mapped || true
+virt-xml "Whonix-Workstation" --add-device --filesystem source=/mnt/workstation-shared,target=shared,type=mount,accessmode=mapped || true
+
+mkdir --parents /var/lib/whonix-libvirt
+touch /var/lib/whonix-libvirt/install.done
diff --git a/overlay/Linux/usr/local/lib/whonix-libvirt/install.dst b/overlay/Linux/usr/local/lib/whonix-libvirt/install.dst
new file mode 100755
index 0000000..eab8393
--- /dev/null
+++ b/overlay/Linux/usr/local/lib/whonix-libvirt/install.dst
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+## Copyright (C) 2019 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -x
+set -e
+
+## {{ Taken from qemu-system-common.postinst.
+# Add the kvm group unless it's already there
+if ! getent group kvm >/dev/null; then
+ addgroup --quiet --system kvm || true
+fi
+## }} Taken from qemu-system-common.postinst.
+
+## {{ Taken from libvirt-bin.postinst.
+if ! getent group libvirt >/dev/null; then
+ addgroup --system libvirt
+fi
+## }} Taken from libvirt-bin.postinst.
+
+## Existence of user "user" is not guaranteed at this point.
+## XXX: Or is it?
+addgroup user kvm >/dev/null || true
+addgroup user libvirt >/dev/null || true
+
+## Create shared directory and adjust permissions
+mkdir --parents /mnt/gateway-shared
+mkdir --parents /mnt/workstation-shared
+chmod 777 /mnt/gateway-shared
+chmod 777 /mnt/workstation-shared
+
+## TODO: proper error handling. '|| true' can probably be removed.
+
+virsh -c qemu:///system net-autostart "default" || true
+virsh -c qemu:///system net-start "default" || true
+virsh -c qemu:///system net-define "/usr/share/whonix-libvirt/xml/Whonix-External.xml" || true
+virsh -c qemu:///system net-define "/usr/share/whonix-libvirt/xml/Whonix-Internal.xml" || true
+virsh -c qemu:///system net-autostart "Whonix-External" || true
+virsh -c qemu:///system net-start "Whonix-External" || true
+virsh -c qemu:///system net-autostart "Whonix-Internal" || true
+virsh -c qemu:///system net-start "Whonix-Internal" || true
+
+## Doing the following in a temporary directory to avoid modified files should
+## this be interrupted in the middle.
+temp_dir="$(mktemp --directory)"
+cp -r /usr/share/whonix-libvirt/xml "$temp_dir"
+
+if virsh capabilities | grep "" ; then
+ true "OK: found KVM"
+else
+ ## replace the 'kvm' domain type with 'qemu'
+ search=""
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+
+ search=""
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+
+ ## https://forums.whonix.org/t/whonix-host-operating-system/3931/251
+ search=""
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+
+ ## https://forums.whonix.org/t/whonix-host-operating-system/3931/284
+ search="1"
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Gateway.xml"
+
+ ## https://forums.whonix.org/t/whonix-host-operating-system/3931/284
+ search="1"
+ replace=""
+ str_replace "$search" "$replace" "$temp_dir/xml/Whonix-Workstation.xml"
+fi
+
+test -f "$temp_dir/xml/Whonix-Gateway.xml"
+test -f "$temp_dir/xml/Whonix-Workstation.xml"
+
+virsh -c qemu:///system define "$temp_dir/xml/Whonix-Gateway.xml" || true
+virsh -c qemu:///system define "$temp_dir/xml/Whonix-Workstation.xml" || true
+
+virt-xml "Whonix-Gateway" --add-device --filesystem source=/mnt/gateway-shared,target=shared,type=mount,accessmode=mapped || true
+virt-xml "Whonix-Workstation" --add-device --filesystem source=/mnt/workstation-shared,target=shared,type=mount,accessmode=mapped || true
+
+mkdir --parents /var/lib/whonix-libvirt
+touch /var/lib/whonix-libvirt/install.done
diff --git a/overlay/Linux/usr/local/lib/whonix-libvirt/live-mode-to-read-only b/overlay/Linux/usr/local/lib/whonix-libvirt/live-mode-to-read-only
new file mode 100755
index 0000000..a0a4d69
--- /dev/null
+++ b/overlay/Linux/usr/local/lib/whonix-libvirt/live-mode-to-read-only
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+## Copyright (C) 2019 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## Similar to persistent-mode-to-read-write.
+
+set -x
+
+error_handler() {
+ exit_code="1"
+}
+
+trap error_handler ERR
+
+exit_code="0"
+
+vm_names_list="$(virsh list --all | awk '{print $2}'| grep -v Name)"
+
+for vm_name_item in $vm_names_list ; do
+ virt-xml "$vm_name_item" --edit --disk readonly=on
+done
+
+## https://phabricator.whonix.org/T914
+if test -f "/var/lib/libvirt/images/Whonix-Gateway.qcow2" ; then
+ chmod --verbose --recursive ugo-w "/var/lib/libvirt/images/Whonix-Gateway.qcow2"
+fi
+if test -f "/var/lib/libvirt/images/Whonix-Workstation.qcow2" ; then
+ chmod --verbose --recursive ugo-w "/var/lib/libvirt/images/Whonix-Workstation.qcow2"
+fi
+
+## "chmod ugo-r" is set during build in chroot:
+## https://github.com/Whonix/Whonix/blob/master/build-steps.d/1800_copy_vms_into_raw
+
+exit "$exit_code"
diff --git a/overlay/Linux/usr/local/lib/whonix-libvirt/persistent-mode-to-read-write b/overlay/Linux/usr/local/lib/whonix-libvirt/persistent-mode-to-read-write
new file mode 100755
index 0000000..0db0c66
--- /dev/null
+++ b/overlay/Linux/usr/local/lib/whonix-libvirt/persistent-mode-to-read-write
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+## Copyright (C) 2019 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## Similar to live-mode-to-read-only.
+
+set -x
+
+error_handler() {
+ exit_code="1"
+}
+
+trap error_handler ERR
+
+exit_code="0"
+
+vm_names_list="$(virsh list --all | awk '{print $2}'| grep -v Name)"
+
+for vm_name_item in $vm_names_list ; do
+ virt-xml "$vm_name_item" --edit --disk readonly=off
+done
+
+chmod --verbose --recursive ug+w "/var/lib/libvirt/images/Whonix-Gateway.qcow2"
+chmod --verbose --recursive ug+w "/var/lib/libvirt/images/Whonix-Workstation.qcow2"
+
+exit "$exit_code"
diff --git a/overlay/Linux/usr/local/proxy_whonix_lib.bash b/overlay/Linux/usr/local/proxy_whonix_lib.bash
new file mode 100755
index 0000000..8d29acb
--- /dev/null
+++ b/overlay/Linux/usr/local/proxy_whonix_lib.bash
@@ -0,0 +1,677 @@
+#!/bin/bash
+# -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=proxy
+export PATH=$PATH:/usr/local/sbin:/usr/local/bin
+
+# . /usr/local/sbin/proxy_whonix_lib.bash || { echo ERROR: loading /usr/local/sbin/proxy_whonix_lib.bash ; exit 2; }
+. /usr/local/bin/proxy_ping_lib.bash || \
+ { echo ERROR: loading /usr/local/bin/proxy_ping_lib.bash ; exit 2; }
+
+## proxy_guest_firewall_config -- /etc/firewall.conf.ws.new
+proxy_guest_firewall_config () {
+ . /usr/local/sbin/proxy_whonix_guest_workstation-firewall.bash || return 2$?
+ source_config_folder
+ iptables_cmd="echo iptables"
+ ip6tables_cmd="echo # ip6tables"
+ main > /etc/firewall.conf.ws.new
+
+ return $?
+}
+
+## proxy_whonix_guest_config
+proxy_whonix_guest_config () {
+ return 0
+}
+
+## proxy_whonix_guest_start
+proxy_whonix_guest_start () {
+ local dire=$1
+
+ [ ! -f /etc/init.d/qemu-guest-agent ] || \
+ proxy_rc_service qemu-guest-agent status >/dev/null \
+ || proxy_rc_service qemu-guest-agent start || return 2$?
+
+ return 0
+}
+
+## proxy_whonix_guest_test
+proxy_whonix_guest_test () {
+ [ -e /dev/virtio-ports/org.qemu.guest_agent.0 ] || \
+ echo WARN: /dev/virtio-ports/org.qemu.guest_agent.0 not created
+ proxy_rc_service qemu-guest-agent status
+
+ return 0
+}
+
+## proxy_whonix_gateway_config
+proxy_whonix_gateway_config () {
+ proxy_whonix_dnsmasq_config gateway 10.0.2.15
+ return 0
+}
+
+## proxy_whonix_dnsmasq_config
+proxy_whonix_dnsmasq_config () {
+ local dire
+
+ [ "$#" -eq 0 ] || dire=$1
+ [ -z "$dire" ] && MODE="$( proxy_whonix_mode )" && dire=$MODE
+ [ -n "$MODE" ] || MODE=host
+
+ proxy_dest_port_wlan_config
+ [ -z "$PORT" -o -z "$DEST" ] && return 1
+
+ # 9040 - no wgetrc polipo
+ # need dnsmasq to 127
+ file=/etc/dnsmasq.conf
+ if [ ! -f $file.$dire ] ; then
+ cp -p $file $file.$dire
+ cat >> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.$dire </dev/null || \
+ proxy_rc_service libvirtd start || \
+ echo WARN: libvirtd crashed - see /var/log/libvirt/libvirtd.log # 2>&1|tee $WLOG
+ proxy_libvirt_status
+ return 0
+}
+
+## proxy_whonix_libvirt_start
+proxy_whonix_libvirt_start () {
+
+ return 0
+}
+
+## proxy_whonix_libvirt_start
+proxy_whonix_libvirt_start () {
+ local domain
+ [ "$#" -ge 1 ] && domain=$1
+
+ if [ ! -e /run/libvirt/libvirt-sock ] || ! proxy_rc_service libvirtd status >/dev/null ; then
+ cp /dev/null /var/log/libvirt/libvirtd.log
+ /etc/init.d/libvirtd status
+ retval=$?
+ [ $retval -eq 32 ] && WARN libvirtd crashed - zapping && /etc/init.d/libvirtd zap
+ [ $retval -eq 0 ] || /etc/init.d/libvirtd start || return 5$? # error: Failed to start livirtd
+ proxy_rc_service libvirtd start || return 3
+ sleep $DELAY
+ fi
+ proxy_libvirt_no_autostart
+ proxy_libvirt_start
+ proxy_libvirt_status
+ proxy_virsh net-list | grep -q Whonix-Internal || virsh net-start Whonix-Internal || return 3
+ proxy_virsh net-list | grep -q Whonix-External || virsh net-start Whonix-External || return 4
+
+ [ -z "$domain" ] && domain="$( proxy_testforge_get_gateway_dom )"
+ [ -z "$domain" ] && echo WARN: null proxy_testforge_get_gateway_dom && \
+ domain=Whonix-Gateway && \
+ echo INFO: set proxy_testforge_get_gateway_dom $domain
+ proxy_libvirt_list | grep -v grep | grep "$domain" || \
+ virsh start $domain || {
+ ret=$?
+ echo ERROR: proxy_whonix_libvirt_start failed virsh start $domain ret=$ret
+ return 5$ret
+ }
+
+ return 0
+}
+
+## proxy_whonix_test
+proxy_whonix_test () {
+ local dire
+ DEBUG proxy_whonix_test $dire
+ [ "$#" -eq 0 ] && dire=$MODE || dire=$1
+
+ [ $dire = ws -o $dire = workstation ] && dire=vda
+
+ if [ $dire = client ] ; then
+ :
+ # dunno - look at netstat? -nle4
+
+ elif [ $dire = vda -o $dire = gateway ] ; then
+ proxy_whonix_guest_test
+
+ elif [ $dire = tor ] ; then
+ proxy_rc_service tor status >/dev/null || \
+ { echo ERROR: $prog tor is not running ; return 2 ; }
+
+ /usr/local/bin/proxy_ping_test.bash to_tor || return 6$?
+
+ elif [ $dire = whonix ] ; then
+ proxy_libvirt_no_autostart
+ proxy_libvirt_clean_virbr1_rules
+
+ proxy_whonix_get_gateway_dom
+ [ -z "$GATEW_DOM" ] && echo WARN: $prog DOM proxy_whonix_get_gateway_dom assuming Whonix-Gateway && DOM=Whonix-Gateway || DOM=$GATEW_DOM
+
+ proxy_virsh list | grep -q $DOM || { echo ERROR: $prog $DOM not running ; return 2 ; }
+
+ /usr/local/bin/proxy_ping_test.bash from_tor || return 6$?
+ fi
+
+ #? gateway
+ if [ $dire = whonix -o $dire = vda -o $dire = tor ] ; then
+ proxy_rc_service polipo status >/dev/null >/dev/null || \
+ { echo ERROR: $prog polipo not running ; return 4 ; }
+ /usr/local/bin/proxy_ping_test.bash polipo || return 9$?
+ elif [ $dire = host -o $dire = tor ] ; then
+ proxy_rc_service privoxy status >/dev/null >/dev/null || \
+ { echo ERROR: $prog privoxy not running ; return 4 ; }
+ /usr/local/bin/proxy_ping_test.bash privoxy || return 9$?
+ fi
+
+ if [ $dire = vda -o $dire = ws -o $dire = workstation ] ; then
+ proxy_clobber_resolv_local 10.152.152.10
+ elif [ $dire = gateway -o $dire = whonix -o $dire = tor ] ; then
+ proxy_rc_service dnsmasq status 2>/dev/null >/dev/null || \
+ { echo ERROR: $prog dnsmasq not running ; return 5 ; }
+ proxy_clobber_resolv_local 127.0.0.1
+ fi
+ /usr/local/bin/proxy_ping_test.bash dns # || return 9$?
+
+ /usr/local/bin/proxy_ping_test.bash $dire || return 6$?
+
+ return 0
+}
+
+# Weher was this
+## rc_host_symlink_etc_fstab
+rc_host_symlink_etc_fstab () {
+ grep -q root=/dev/vda /proc/cmdline
+ PROXY_IS_VDA=$?
+if [ $PROXY_IS_VDA -eq 0 ] ; then
+ [ -h /etc/fstab ] && [ -f /etc/fstab.vda ] && \
+ rm -f /etc/fstab && ln -s /etc/fstab.vda /etc/fstab
+ return 1
+# else
+# [ -h /etc/fstab ] && [ -f /etc/fstab.4TA ] && \
+# rm -f /etc/fstab && ln -s /etc/fstab.4TA /etc/fstab
+ fi
+
+ return 0
+}
+
+## proxy_vda_config
+proxy_vda_config () {
+
+ rc_host_symlink_etc_fstab
+ sed -e 's/^#x1/x1/' -i /etc/inittab #
+
+ if false ; then
+ sed -e 's/^#//' -i $PREFIX/etc/modules_load.d/vda*conf
+ if [ ! -h /etc/modules_load.d/vda_mods.conf ] ; then
+ ln -s $PREFIX/etc/modules_load.d/vda*conf /etc/modules_load.d/
+ fi
+ fi
+ if false ; then
+ [ -f /etc/firewall.conf.vda ] && \
+ cp -p /etc/firewall.conf.vda /etc/firewall.conf
+ fi
+ return 0
+}
+
+##
+old_proxy_vda_config () {
+
+ [ -f /etc/inittab ] && sed -e 's/^#x1/x1/' -i /etc/inittab
+
+ return 0
+}
+
+## proxy_vda_whonix_config
+proxy_vda_whonix_config () {
+ local dir=vda
+
+ DEST=10.152.152.10
+ PROXY_WLAN=eth0
+ proxy_host_whonix_config $dire $DEST 9053 $PROXY_WLAN
+
+ return $?
+}
+
+## proxy_quest_config
+proxy_quest_config () {
+
+ proxy_vda_config
+
+ sed -e 's/^#//' -i $PREFIX/etc/modules_load.d/vda*conf
+ if [ ! -h /etc/modules_load.d/vda_mods.conf ] ; then
+ cp -np $PREFIX/etc/modules_load.d/vda*conf /etc/modules-load.d/
+ fi
+ return 0
+}
+
+## proxy_whonix_dnsmasq_start
+proxy_whonix_dnsmasq_start () {
+ local dire
+ local service=dnsmasq
+
+ [ "$#" -eq 0 ] || dire=$1
+ [ -z "$dire" ] && MODE="$( proxy_whonix_mode )" && dire=$MODE
+ [ -n "$MODE" ] || MODE=host
+
+ DEBUG proxy_whonix_dnsmasq_start $dire $PROXY_WLAN
+
+ proxy_whonix_config $dire || return 1$?
+
+ PROXY_WLAN=$( proxy_get_if )
+ [ -z "$PROXY_WLAN" ] && echo ERROR: $prog empty PROXY_WLAN && return 4
+
+ sed -e "s/wlan[0-9]/$PROXY_WLAN/" -i /etc/dnsmasq.conf.$dire
+ if diff /etc/dnsmasq.conf.$dire /etc/dnsmasq.conf >/dev/null ; then
+ proxy_rc_service dnsmasq status >/dev/null || \
+ proxy_ping_dnsmasq_start || return 8$?
+ else
+ proxy_rc_service dnsmasq status >/dev/null && \
+ proxy_ping_dnsmasq_stop
+ cp -p /etc/dnsmasq.conf.$dire /etc/dnsmasq.conf
+ proxy_ping_dnsmasq_start || return 8$?
+ fi
+
+ return 0
+}
+
+## proxy_whonix_privoxy_start
+proxy_whonix_polipo_start () {
+ local dire
+ local service=polipo
+
+ [ $# -eq 1 ] && dire=$1
+ [ -z "$dire" ] && dire="$( proxy_whonix_mode )"
+ DEBUG proxy_whonix_start_$service $dire
+
+ proxy_whonix_config $dire || \
+ echo WARN: proxy_whonix_polipo_start proxy_whonix_config $dire $? # return 1$?
+
+ sed -e "s/wlan[0-9]/$PROXY_WLAN/" -e "s/eth[0-9]/$PROXY_WLAN/" -i /etc/polipo/config.$dire
+
+ if ! diff /etc/polipo/config.$dire /etc/polipo/config ; then
+ cp -p /etc/polipo/config.$dire /etc/polipo/config
+ proxy_rc_service $service restart || return 2$?
+ else
+ proxy_rc_service $service status >/dev/null || \
+ proxy_rc_service $service start||return 3$
+ fi
+
+ return 0
+}
+
+## proxy_whonix_host_prepare_blocks
+proxy_whonix_host_prepare_blocks () {
+ if [ ! -s /etc/firewall.conf.block ] ; then
+ if [ -f /usr/local/etc/firewall.conf.block ] ; then
+ echo "WARN: $prog copying /usr/local/etc/firewall.conf.block"
+ cp -p /usr/local/etc/firewall.conf.block /etc/firewall.conf.block
+ else
+ echo "ERROR: $prog missing /usr/local/etc/firewall.conf.block"
+ return 1
+ fi
+ fi
+ return 0
+}
+
+## proxy_whonix_host_add_block
+proxy_whonix_host_add_block () {
+ local elt tab ip
+
+ # PROXY_WLAN=$( proxy_get_if )
+ # [ $? -ne 0 -o -z "$PROXY_WLAN" ] && echo ERROR: $prog null interface && return 1
+ if [ "$#" -eq 0 ] ; then
+ proxy_whonix_host_prepare_blocks \| return 1$?
+ set - $( cat /etc/firewall.conf.block )
+ fi
+ # DEBUG "$prog adding $*"
+ [ -f /etc/firewall.conf.newer ] || \
+ cp -p /etc/firewall.conf /etc/firewall.conf.newer
+ for elt in wlan virbr1 ; do
+ [ $elt = wlan ] && tab=INPUT || tab=LIBVIRT_FWI
+ grep -q "^# blocks $elt" /etc/firewall.conf.newer || {
+ echo ERROR: maker not found "^# blocks $elt" in /etc/firewall.conf.newer
+ return 2
+ }
+ sed -e "/^# blocks $elt/,\$d" /etc/firewall.conf.newer > /etc/firewall.conf.$$
+ echo "# blocks $elt" >> /etc/firewall.conf.$$
+ for ip in $* ; do
+ grep -q $ip /etc/firewall.conf.block || \
+ grep -q $ip /etc/firewall.conf.block.newer || \
+ echo $ip >> /etc/firewall.conf.block.newer
+ grep -q -e "A $tab -s $ip" /etc/firewall.conf.newer && continue
+ echo "-A $tab -s $ip -p tcp -j DROP" >> /etc/firewall.conf.$$
+ DEBUG "$prog -A $tab -s $ip -m tcp -p tcp -j DROP"
+ done
+ sed -e "1,/^# blocks $elt/d" /etc/firewall.conf.newer >> /etc/firewall.conf.$$
+ mv /etc/firewall.conf.$$ /etc/firewall.conf.newer
+ done
+ return 0
+}
+
+## proxy_whonix_host_online
+proxy_whonix_host_online () {
+ [ -n "$PROXY_WLAN" ] || PROXY_WLAN=$( proxy_get_if ) || return 1$?
+ [ -z "$PROXY_WLAN" ] && echo ERROR: empty PROXY_WLAN && return 2
+ if [ -x /etc/init.d/NetworkManager ] ; then
+ /etc/init.d/NetworkManager status || /etc/init.d/NetworkManager start || return 3
+else
+ proxy_rc_service NetworkManager status >/dev/null \
+ || proxy_rc_service NetworkManager start || return 3$?
+fi
+ nm-online -t 0 -x || return 4$?
+
+ return 0
+}
+
+## proxy_whonix_down - call when the network goes down
+proxy_whonix_down () {
+# $PREFIX/bin/proxy_ping_test.bash "$MODE" || return 1$?
+ proxy_ping_online && return 0 # dont do anything
+ # nothing to do?
+ return 0
+}
+
+## proxy_whonix_up - call when the network comes up
+proxy_whonix_up () {
+ # $PREFIX/bin/proxy_ping_test.bash "$MODE" || return 1$?
+ proxy_ping_online || return 0 # dont do anything
+ return 0
+}
+
+## proxy_whonix_start_wget
+proxy_whonix_start_wget () {
+ return 0
+ if [ -f /etc/wgetrc ] ; then
+ sp=https://127.0.0.1:3128
+ grep -q ^https_proxy /etc/wgetrc && \
+ sed -e "s@https_proxy.*@https_proxy = $sp@" -i /etc/wgetrc
+ grep -q ^https_proxy /etc/wgetrc && \
+ echo "https_proxy = $sp" >> /etc/wgetrc
+ grep -q ^http_proxy /etc/wgetrc && \
+ sed -e "s@http_proxy.*@http_proxy = $sp@" -i /etc/wgetrc
+ grep -q ^http_proxy /etc/wgetrc || \
+ echo "http_proxy = $sp" >> /etc/wgetrc
+ fi
+
+ sp=http://127.0.0.1:3128
+ for elt in http https ; do
+ grep -q ^$elt_proxy /etc/wgetrc && \
+ sed -e "s@$elt_proxy.*@$elt_proxy = $sp@" -i /etc/wgetrc || \
+ echo "$elt_proxy = $sp" >> /etc/wgetrc
+ done
+
+
+ return 0
+}
+
+proxy_libvirt_clean_iptables () {
+ local i int dir dcp prot port
+
+ for dir in i ; do
+ for int in virbr2 virbr1; do
+ dcp=67
+ [ $dir = i ] || dcp=68
+ for port in 53 $dcp ; do
+ [ $dir = i ] && table=INP || table=OUT
+ for prot in udp tcp; do
+ proxy_iptables_save | grep -q -e "-A LIBVIRT_$table -i $int -p $prot -m $prot --dport $port -j ACCEPT" || continue
+ iptables -D LIBVIRT_$table -$dir $int -p $prot -m $prot --dport $port -j ACCEPT || \
+ echo WARN: $? -D LIBVIRT_$table -$dir $int -p $prot -m $prot --dport $port -j ACCEPT
+ done
+ done
+ done
+ done
+
+ for dir in o ; do
+ for int in virbr2 virbr1; do
+ dcp=68
+ [ $dir = o ] || dcp=67
+ for port in 53 68 ; do
+ table=OUT
+ [ $dir = i ] && table=INP
+ for prot in udp tcp; do
+ proxy_iptables_save | grep -q -e "-A LIBVIRT_$table -i $int -p $prot -m $prot --dport $port -j ACCEPT" || continue
+ iptables -D LIBVIRT_$table -$dir $int -p $prot -m $prot --dport $port -j ACCEPT || \
+ echo WARN: $? -D LIBVIRT_$table -$dir $int -p $prot -m $prot --dport $port -j ACCEPT
+ done
+ done
+ done
+ done
+
+ return 0
+}
+
+base=proxy_whonix_lib
+if [ -x /usr/bin/basename ] && [ $( /usr/bin/basename -- $0 .bash ) = $base ] ; then
+ [ "$#" -eq 0 ] && exit 0
+ [ "$#" -eq 1 ] && [ "$1" = '-h' -o "$1" = '--help' ] && \
+ echo USAGE: $0 && grep '^[a-z].*()\|^## ' $0 | sed -e 's/().*//'|sort && \
+ exit 0
+ DEBUG $base "$@"
+ eval "$@"
+ exit $?
+ fi
diff --git a/overlay/Linux/usr/local/sbin/debian_whonix_tor.bash b/overlay/Linux/usr/local/sbin/debian_whonix_tor.bash
new file mode 100755
index 0000000..9df5b96
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/debian_whonix_tor.bash
@@ -0,0 +1,34 @@
+#!/bin/sh
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=privacy
+[ -z "$PRIV_TOR_OWNER" ] && grep -q ^debian-tor /etc/passwd && PRIV_TOR_OWNER=debian-tor
+
+# Nov 09 21:00:27 host vanguards[715]: WARNING[Mon Nov 09 21:00:27 2020]: Tor daemon connection failed: [Errno 24] Too many open files. Trying again...
+systemctl stop vanguards
+systemctl stop onion-grater
+sh /etc/rc.local
+
+#su -c 'tor --verify-config' -s /bin/sh $PRIV_TOR_OWNER || exit 1
+tor --verify-config | grep -v 'notice\|DisableNetwork'
+rm -f /etc/torrc.d/*~
+
+netstat -nlp -t inet|grep 15:90 || { echo ERROR: alrady running ; exit 2 ; }
+
+cp /dev/null /run/tor/log.err
+cp /dev/null /run/tor/log.log
+rm -f /usr/local/etc/torrc.d/*~ /etc/torrc.d/*~
+
+#su -c '/etc/init.d/tor stop' -s /bin/sh $PRIV_TOR_OWNER
+#sleep 5
+
+# su -c '/etc/init.d/tor start' -s /bin/sh $PRIV_TOR_OWNER
+systemctl start tor || exit 4$?
+
+sleep 10
+
+sed -e '/configured a non-loopback address/d' /run/tor/log.*
+
+[ -f /run/tor/log.err ] && cat /run/tor/log.err && exit 5
+
+grep % /run/tor/log.*
diff --git a/overlay/Linux/usr/local/sbin/privacy_whonix-gateway-firewall.bash b/overlay/Linux/usr/local/sbin/privacy_whonix-gateway-firewall.bash
new file mode 100755
index 0000000..141c6a2
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/privacy_whonix-gateway-firewall.bash
@@ -0,0 +1,827 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+prog=$( basename $0 .bash )
+PREFIX=/usr/local
+ROLE=privacy
+
+[ -f /usr/local/etc/testforge/testforge.bash ] && . /usr/local/etc/testforge/testforge.bash \
+ || { echo >&2 ERROR: $prog "/usr/local/etc/testforge/testforge.bash" ; exit 1 ; }
+[ -z "$PRIV_TOR_OWNER" ] && grep -q ^debian-tor /etc/passwd && PRIV_TOR_OWNER=debian-tor
+[ -z "$PRIV_TOR_OWNER" ] && grep -q ^tor /etc/passwd && PRIV_TOR_OWNER=tor
+
+#set -- -x
+DEBUG=
+WHONIX_HOST=0
+WHONIX_GATE=1
+
+SSH_SERVICE=22
+BOOTPC_SERVICE=68
+BOOTPS_SERVICE=67
+NETBIOSNS_SERVICE=137
+NETBIOSDG_SERVICE=138
+
+PRIV_WHONIX_EXTERNAL_NET=10.0.2.0/24
+# 10.152.152.10 gateway
+# 10.152.152.11 work
+PRIV_WHONIX_INTERNAL_NET=10.152.152.0/24
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## Copyright (C) 2014 - 2015 Jason Mehring
+## See the file COPYING for copying conditions.
+
+ALLOW_GATEWAY_USER_USER=1
+GATEWAY_ALLOW_INCOMING_SSH=0
+GATEWAY_ALLOW_INCOMING_ICMP=0
+
+#### meta start
+#### project Whonix
+#### category networking and firewall
+#### description
+## firewall script
+#### meta end
+
+## --reject-with
+## http://ubuntuforums.org/showthread.php?p=12011099
+
+## Set to icmp-admin-prohibited because icmp-port-unreachable caused
+## confusion. icmp-port-unreachable looks like a bug while
+## icmp-admin-prohibited hopefully makes clear it is by design.
+
+set -e
+
+error_handler() {
+ echo "$0 ##################################################"
+ echo "$0 ERROR: Whonix firewall script failed!"
+ echo "$0 ##################################################"
+
+ exit 1
+}
+
+trap "error_handler" ERR
+
+init() {
+ output_cmd "OK: Loading Whonix firewall..."
+
+ set -o pipefail
+ set -o errtrace
+}
+
+source_config_folder() {
+ shopt -s nullglob
+ local i
+ for i in \
+ /etc/whonix_firewall.d/*.conf \
+ /rw/config/whonix_firewall.d/*.conf \
+ /usr/local/etc/whonix_firewall.d/*.conf \
+ ; do
+ bash_n_exit_code="0"
+ bash_n_output="$(bash -n "$i" 2>&1)" || { bash_n_exit_code="$?" ; true; };
+ if [ ! "$bash_n_exit_code" = "0" ]; then
+ output_cmd "ERROR: Invalid config file: $i
+ bash_n_exit_code: $bash_n_exit_code
+ bash_n_output:
+ $bash_n_output" >&2
+ exit 1
+ fi
+ source "$i"
+ done
+}
+
+variables_defaults() {
+ [ -n "$iptables_cmd" ] || iptables_cmd="iptables --wait"
+ [ -n "$ip6tables_cmd" ] || ip6tables_cmd="ip6tables --wait"
+
+ [ -n "$WORKSTATION_TRANSPARENT_TCP" ] || WORKSTATION_TRANSPARENT_TCP=1
+ [ -n "$WORKSTATION_TRANSPARENT_DNS" ] || WORKSTATION_TRANSPARENT_DNS=1
+ [ -n "$WORKSTATION_ALLOW_SOCKSIFIED" ] || WORKSTATION_ALLOW_SOCKSIFIED=1
+ [ -n "$CONTROL_PORT_FILTER_PROXY_ENABLE" ] || CONTROL_PORT_FILTER_PROXY_ENABLE=1
+ [ -n "$GATEWAY_ALLOW_INCOMING_DIR_PORT" ] || GATEWAY_ALLOW_INCOMING_DIR_PORT=0
+ [ -n "$GATEWAY_ALLOW_INCOMING_OR_PORT" ] || GATEWAY_ALLOW_INCOMING_OR_PORT=0
+ [ -n "$DIR_PORT" ] || DIR_PORT=80
+ [ -n "$OR_PORT" ] || OR_PORT=443
+ [ -n "$GATEWAY_TRANSPARENT_TCP" ] || GATEWAY_TRANSPARENT_TCP=0
+ [ -n "$GATEWAY_TRANSPARENT_UDP" ] || GATEWAY_TRANSPARENT_UDP=0
+ [ -n "$GATEWAY_TRANSPARENT_DNS" ] || GATEWAY_TRANSPARENT_DNS=0
+ [ -n "$ALLOW_GATEWAY_ROOT_USER" ] || ALLOW_GATEWAY_ROOT_USER=0
+ [ -n "$ALLOW_GATEWAY_USER_USER" ] || ALLOW_GATEWAY_USER_USER=0
+ [ -n "$GATEWAY_ALLOW_INCOMING_SSH" ] || GATEWAY_ALLOW_INCOMING_SSH=0
+ [ -n "$GATEWAY_ALLOW_INCOMING_ICMP" ] || GATEWAY_ALLOW_INCOMING_ICMP=0
+
+ ## Get Tor username, distro specific!
+ [ -n "$TOR_USER" ] || TOR_USER=$PRIV_TOR_OWNER
+
+ ## Get user uids.
+#!? [ -n "$CLEARNET_USER" ] || CLEARNET_USER="$(id -u clearnet)"
+ [ -n "$USER_USER" ] || USER_USER="$(id -u user)" || true
+ [ -n "$ROOT_USER" ] || ROOT_USER="$(id -u root)"
+#!? [ -n "$TUNNEL_USER" ] || TUNNEL_USER="$(id -u tunnel)"
+ [ -n "$SDWDATE_USER" ] || SDWDATE_USER="$(id -u sdwdate)"
+ [ -n "$WHONIXCHECK_USER" ] || WHONIXCHECK_USER="$(id -u whonixcheck)"
+
+ ## No NAT for clearnet user.
+ [ -n "$CLEARNET_USER" ] && NO_NAT_USERS+=" $CLEARNET_USER"
+
+ ## No NAT for tunnel user.
+ [ -n "$TUNNEL_USER" ] && NO_NAT_USERS+=" $TUNNEL_USER"
+
+ ## No NAT for user user.
+ ## DISABLED BY DEFAULT. For testing/debugging only.
+ if [ "$ALLOW_GATEWAY_USER_USER" = "1" ]; then
+ if [ "$USER_USER" = "" ]; then
+ output_cmd "INFO: USER_USER is unset. Not adding USER_USER to NO_NAT_USERS."
+ else
+ NO_NAT_USERS+=" $USER_USER"
+ fi
+ fi
+
+ ## No NAT for root user.
+ ## DISABLED BY DEFAULT. For testing/debugging only.
+ if [ "$ALLOW_GATEWAY_ROOT_USER" = "1" ]; then
+ NO_NAT_USERS+=" $ROOT_USER"
+ fi
+
+ ## Whonix-Gateway firewall does not support TUNNEL_FIREWALL_ENABLE=true yet.
+ ## It only supports VPN_FIREWALL="1".
+ ## In case someone confused this setting, i.e. using TUNNEL_FIREWALL_ENABLE=true
+ ## since this is how it is done on Whonix-Workstation, then gracefully enable
+ ## VPN_FIREWALL="1" to prevent users shooting their own feet.
+ if [ "$TUNNEL_FIREWALL_ENABLE" = "true" ]; then
+ VPN_FIREWALL="1"
+ fi
+
+ ## No NAT for Tor itself,
+ ## unless VPN_FIREWALL mode is enabled.
+ if [ "$VPN_FIREWALL" = "1" ]; then
+ true
+ else
+ NO_NAT_USERS+=" $TOR_USER"
+ fi
+
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ [ -n "$INT_IF" ] || INT_IF="vif+"
+ [ -n "$INT_TIF" ] || INT_TIF="vif+"
+ fi
+
+ ## External interface
+ [ -n "$EXT_IF" ] || EXT_IF="eth0"
+ ## Internal interface
+ [ -n "$INT_IF" ] || INT_IF="eth1"
+ ## Internal "tunnel" interface, usually the same as
+ ## the Internal interface unless using vpn tunnels
+ ## between workstations and gateway
+ [ -n "$INT_TIF" ] || INT_TIF="eth1"
+
+ if [ "$NON_TOR_GATEWAY" = "" ]; then
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ NON_TOR_GATEWAY=""
+ else
+ ## 10.0.2.2-10.0.2.24: VirtualBox DHCP
+ NON_TOR_GATEWAY="\
+ 127.0.0.0-127.0.0.24 \
+ 192.168.0.0-192.168.0.24 \
+ 192.168.1.0-192.168.1.24 \
+ 10.152.152.0-10.152.152.24 \
+ 10.0.2.2-10.0.2.24 \
+ "
+ fi
+ fi
+
+ [ -n "$VPN_INTERFACE" ] || VPN_INTERFACE="tun0"
+
+ ## Destinations you do not routed through VPN, only for Whonix-Gateway.
+ if [ "$LOCAL_NET" = "" ]; then
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ LOCAL_NET="\
+ 127.0.0.0-127.0.0.24 \
+ 10.137.0.0-10.138.255.255 \
+ "
+ else
+ ## 10.0.2.2/24: VirtualBox DHCP
+ LOCAL_NET="\
+ 127.0.0.0-127.0.0.24 \
+ 192.168.0.0-192.168.0.24 \
+ 192.168.1.0-192.168.1.24 \
+ 10.152.152.0-10.152.152.24 \
+ 10.0.2.2-10.0.2.24 \
+ "
+ fi
+ fi
+
+ if [ "$WORKSTATION_DEST_SOCKSIFIED" = "" ]; then
+ ## 10.152.152.10 - Non-Qubes-Whonix-Gateway IP
+ ##
+ ## 10.137.0.0/8 - persistent Qubes-Whonix-Gateway IP range
+ ## 10.138.0.0/8 - DispVM Qubes-Whonix-Gateway IP range
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ ## https://forums.whonix.org/t/whonix-gateway-not-reachable/7484/16
+ ## 10.152.152.10 is hardcoded in some places.
+ WORKSTATION_DEST_SOCKSIFIED="10.137.0.0/16,10.138.0.0/16,10.152.152.10"
+ else
+ WORKSTATION_DEST_SOCKSIFIED="10.152.152.10"
+ fi
+ fi
+
+ ## The following ports are used
+ ## - here in /usr/bin/whonix_firewall (package: whonix-gw-firewall)
+ ## - by Tor in /usr/share/tor/tor-service-defaults-torrc (package: anon-gw-anonymizer-config)
+ ##
+ ## The following applications will be separated, preventing identity
+ ## correlation through circuit sharing.
+
+ ## Transparent Proxy Ports for Whonix-Workstation
+ [ -n "$TRANS_PORT_WORKSTATION" ] || TRANS_PORT_WORKSTATION="9040"
+ [ -n "$DNS_PORT_WORKSTATION" ] || DNS_PORT_WORKSTATION="5300"
+
+ ## Transparent Proxy Ports for Whonix-Gateway
+ [ -n "$TRANS_PORT_GATEWAY" ] || TRANS_PORT_GATEWAY="9041"
+ [ -n "$DNS_PORT_GATEWAY" ] || DNS_PORT_GATEWAY="5400"
+
+ ## Control Port Filter Proxy Port
+ [ -n "$CONTROL_PORT_FILTER_PROXY_PORT" ] || CONTROL_PORT_FILTER_PROXY_PORT="9051"
+
+ [ -n "$GATEWAY_ALLOW_INCOMING_FLASHPROXY" ] || GATEWAY_ALLOW_INCOMING_FLASHPROXY="0"
+ [ -n "$FLASHPROXY_PORT" ] || FLASHPROXY_PORT="9000"
+
+ ## Socks Ports for per application circuits.
+ [ -n "$SOCKS_PORT_TOR_DEFAULT" ] || SOCKS_PORT_TOR_DEFAULT="9050"
+ [ -n "$SOCKS_PORT_TB" ] || SOCKS_PORT_TB="9100"
+ [ -n "$SOCKS_PORT_IRC" ] || SOCKS_PORT_IRC="9101"
+ [ -n "$SOCKS_PORT_TORBIRDY" ] || SOCKS_PORT_TORBIRDY="9102"
+ [ -n "$SOCKS_PORT_IM" ] || SOCKS_PORT_IM="9103"
+ [ -n "$SOCKS_PORT_APT_GET" ] || SOCKS_PORT_APT_GET="9104"
+ [ -n "$SOCKS_PORT_GPG" ] || SOCKS_PORT_GPG="9105"
+ [ -n "$SOCKS_PORT_SSH" ] || SOCKS_PORT_SSH="9106"
+ [ -n "$SOCKS_PORT_GIT" ] || SOCKS_PORT_GIT="9107"
+ [ -n "$SOCKS_PORT_SDWDATE" ] || SOCKS_PORT_SDWDATE="9108"
+ [ -n "$SOCKS_PORT_WGET" ] || SOCKS_PORT_WGET="9109"
+ [ -n "$SOCKS_PORT_WHONIXCHECK" ] || SOCKS_PORT_WHONIXCHECK="9110"
+ [ -n "$SOCKS_PORT_BITCOIN" ] || SOCKS_PORT_BITCOIN="9111"
+ [ -n "$SOCKS_PORT_PRIVOXY" ] || SOCKS_PORT_PRIVOXY="9112"
+ [ -n "$SOCKS_PORT_POLIPO" ] || SOCKS_PORT_POLIPO="9113"
+ [ -n "$SOCKS_PORT_WHONIX_NEWS" ] || SOCKS_PORT_WHONIX_NEWS="9114"
+ [ -n "$SOCKS_PORT_TBB_DOWNLOAD" ] || SOCKS_PORT_TBB_DOWNLOAD="9115"
+ [ -n "$SOCKS_PORT_TBB_GPG" ] || SOCKS_PORT_TBB_GPG="9116"
+ [ -n "$SOCKS_PORT_CURL" ] || SOCKS_PORT_CURL="9117"
+ [ -n "$SOCKS_PORT_RSS" ] || SOCKS_PORT_RSS="9118"
+ [ -n "$SOCKS_PORT_TORCHAT" ] || SOCKS_PORT_TORCHAT="9119"
+ [ -n "$SOCKS_PORT_MIXMASTERUPDATE" ] || SOCKS_PORT_MIXMASTERUPDATE="9120"
+ [ -n "$SOCKS_PORT_MIXMASTER" ] || SOCKS_PORT_MIXMASTER="9121"
+ [ -n "$SOCKS_PORT_KDE" ] || SOCKS_PORT_KDE="9122"
+ [ -n "$SOCKS_PORT_GNOME" ] || SOCKS_PORT_GNOME="9123"
+ [ -n "$SOCKS_PORT_APTITUDE" ] || SOCKS_PORT_APTITUDE="9124"
+ [ -n "$SOCKS_PORT_YUM" ] || SOCKS_PORT_YUM="9125"
+ [ -n "$SOCKS_PORT_TBB_DEFAULT" ] || SOCKS_PORT_TBB_DEFAULT="9150"
+
+ ## For testing purposes only.
+ ## To test if prerouting redirection rules for socksified interfere with transparent torification.
+ ## https://phabricator.whonix.org/T462
+ #[ -n "$SOCKS_PORT_HTTP" ] || SOCKS_PORT_HTTP="80"
+ #[ -n "$SOCKS_PORT_SSL" ] || SOCKS_PORT_SSL="443"
+
+ ## Adding more Socks Ports here should no longer be necessary.
+ ## There are already lots of custom ports prepared that you can use.
+ ## See documentation:
+ ## https://www.whonix.org/wiki/Stream_Isolation
+ ##
+ ## Additional Socks Ports for per application circuits could be
+ ## added here, but you would have to:
+ ## - Edit '/usr/local/etc/torrc.d/50_user.conf' to add more 'SocksPort's.
+ ## - And 'sudo service tor@default reload' afterwards.
+ ## - Add more socks port variables to Whonix firewall configuration.
+ ## (For example to '/etc/whonix_firewall.d/50_user.conf'.)
+ ## Follow the 'SOCKS_PORT_...' naming scheme.
+ ## (For example 'SOCKS_PORT_CUSTOM_ONE', 'SOCKS_PORT_CUSTOM_TWO', etc.)
+ ## - And issue "sudo /usr/bin/whonix_firewall" afterwards.
+
+ socks_ports_list="$(compgen -v | grep SOCKS\_PORT\_)"
+}
+
+ipv4_defaults() {
+ lsmod | grep -q iptable_filter || modprobe iptable_filter
+ ## Set secure defaults.
+ $iptables_cmd -P INPUT DROP
+
+ ## FORWARD rules does not actually do anything if forwarding is disabled. Better be safe just in case.
+ $iptables_cmd -P FORWARD DROP
+
+ ## Will be lifted below.
+ $iptables_cmd -P OUTPUT DROP
+}
+
+ipv4_preparation() {
+ lsmod | grep -q nf_nat || modprobe nf_nat
+ lsmod | grep -q iptable_mangle || modprobe iptable_mangle
+
+ ## Flush old rules.
+ $iptables_cmd -F
+ $iptables_cmd -X
+ $iptables_cmd -t nat -F
+ $iptables_cmd -t nat -X
+ $iptables_cmd -t mangle -F
+ $iptables_cmd -t mangle -X
+}
+
+ipv4_drop_invalid_incoming_packages() {
+ lsmod | grep -q nf_conntrack || modprobe nf_conntrack
+
+ ## DROP MARTIANS
+## https://www.cyberciti.biz/faq/linux-log-suspicious-martian-packets-un-routable-source-addresses/
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 10.0.0.0/8 -j LOG --log-prefix "iptables_martian_DROP SPOOF A: "
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 172.16.0.0/12 -j LOG --log-prefix "iptables_martian_DROP SPOOF B: "
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 192.168.0.0/16 -j LOG --log-prefix "iptables_martian_DROP SPOOF C: "
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 224.0.0.0/4 -j LOG --log-prefix "iptables_martian_DROP MULTICAST D: "
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 240.0.0.0/5 -j LOG --log-prefix "iptables_martian_DROP SPOOF E: "
+ $iptables_cmd -A INPUT -i $WLAN_IF -d 127.0.0.0/8 -j LOG --log-prefix "iptables_martian_DROP LOOPBACK: "
+
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 10.0.0.0/8 -j DROP
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 172.16.0.0/12 -j DROP
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 192.168.0.0/16 -j DROP
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 224.0.0.0/4 -j DROP
+ $iptables_cmd -A INPUT -i $WLAN_IF -s 240.0.0.0/5 -j DROP
+ $iptables_cmd -A INPUT -i $WLAN_IF -d 127.0.0.0/8 -j DROP
+
+ ## DROP INVALID
+ $iptables_cmd -A INPUT -m conntrack --ctstate INVALID -j DROP
+ $iptables_cmd -A INPUT -m state --state INVALID -j DROP
+
+ ## DROP INVALID SYN PACKETS
+ $iptables_cmd -A INPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
+ $iptables_cmd -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
+ $iptables_cmd -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
+
+ ## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
+ $iptables_cmd -A INPUT -f -j DROP
+
+ ## DROP INCOMING MALFORMED XMAS PACKETS
+ $iptables_cmd -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
+
+ ## DROP INCOMING MALFORMED NULL PACKETS
+ $iptables_cmd -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
+}
+
+qubes() {
+ lsmod | grep -q xt_owner || modprobe xt_owner
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true "timesync-fail-closed mode, skipping rest of function $FUNCNAME"
+ return 0
+ fi
+
+ if [ -e /run/qubes/this-is-netvm ] || [ -e /run/qubes/this-is-proxyvm ]; then
+ local int_if_item
+
+ for int_if_item in $INT_IF; do
+ ## Allow connections from port 8082 of internal vif interface for tinyproxy
+ ## tinyproxy is responsible to handle TemplateVMs updates.
+ $iptables_cmd -A INPUT -i "$int_if_item" -p tcp -m tcp --dport 8082 -j ACCEPT
+ $iptables_cmd -A OUTPUT -o "$int_if_item" -p tcp -m tcp --sport 8082 -j ACCEPT
+ done
+
+ ## Qubes pre-routing. Will be able to intercept traffic destined for
+ ## 10.137.255.254 to be re-routed to tinyproxy.
+ $iptables_cmd -t nat -N PR-QBS-SERVICES
+ $iptables_cmd -t nat -A PREROUTING -j PR-QBS-SERVICES
+
+ for int_if_item in $INT_IF; do
+ ## Redirects traffic destined for 10.137.255.154 to port 8082 (tinyproxy).
+ $iptables_cmd -t nat -A PR-QBS-SERVICES -d 10.137.255.254/32 -i "$int_if_item" -p tcp -m tcp --dport 8082 -j REDIRECT
+ done
+
+ ## Forward tinyproxy output to port 5300/9040 on internal (Tor) interface (eth1) to be
+ ## able to connect to Internet (via Tor) to proxy updates for TemplateVM.
+ $iptables_cmd -t nat -A OUTPUT -p udp -m owner --uid-owner tinyproxy -m conntrack --ctstate NEW -j DNAT --to "127.0.0.1:${DNS_PORT_GATEWAY}"
+ $iptables_cmd -t nat -A OUTPUT -p tcp -m owner --uid-owner tinyproxy -m conntrack --ctstate NEW -j DNAT --to "127.0.0.1:${TRANS_PORT_GATEWAY}"
+
+ ## The same for squid from qubes-updates-cache, which runs as user vm-updates.
+ if getent passwd vm-updates >/dev/null; then
+ $iptables_cmd -t nat -A OUTPUT -p udp -m owner --uid-owner vm-updates -m conntrack --ctstate NEW -j DNAT --to "127.0.0.1:${DNS_PORT_GATEWAY}"
+ $iptables_cmd -t nat -A OUTPUT -p tcp -m owner --uid-owner vm-updates -m conntrack --ctstate NEW -j DNAT --to "127.0.0.1:${TRANS_PORT_GATEWAY}"
+ fi
+
+ ## https://github.com/QubesOS/qubes-issues/issues/3201#issuecomment-338646742
+ $iptables_cmd -A OUTPUT -p udp -m owner --uid-owner tinyproxy -m conntrack --ctstate NEW -d 127.0.0.1 --dport "${DNS_PORT_GATEWAY}" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p tcp -m owner --uid-owner tinyproxy -m conntrack --ctstate NEW -d 127.0.0.1 --dport "${TRANS_PORT_GATEWAY}" -j ACCEPT
+ fi
+}
+
+ipv4_input_rules() {
+ ## Traffic on the loopback interface is accepted.
+ $iptables_cmd -A INPUT -i lo -j ACCEPT
+
+ ## Established incoming connections are accepted.
+ $iptables_cmd -A INPUT -m state --state ESTABLISHED -j ACCEPT
+
+ ## Drop all incoming ICMP traffic by default.
+ ## All incoming connections are dropped by default anyway, but should a user
+ ## allow incoming ports (such as for incoming SSH or FlashProxy), ICMP should
+ ## still be dropped to filter for example ICMP time stamp requests.
+ if [ ! "$GATEWAY_ALLOW_INCOMING_ICMP" = "1" ]; then
+ $iptables_cmd -A INPUT -p icmp -j DROP
+ fi
+
+ ## Allow all incoming connections on the virtual VPN network interface,
+ ## when VPN_FIREWALL mode is enabled.
+ ## DISABLED BY DEFAULT.
+ if [ "$VPN_FIREWALL" = "1" ]; then
+ $iptables_cmd -A INPUT -i "$VPN_INTERFACE" -j ACCEPT
+ fi
+
+ local ext_if_item
+
+ for ext_if_item in $EXT_IF; do
+ ## Allow incoming SSH connections on the external interface.
+ ## DISABLED BY DEFAULT. For testing/debugging only.
+ if [ "$GATEWAY_ALLOW_INCOMING_SSH" = "1" ]; then
+ $iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --dport 22 -j ACCEPT
+ fi
+
+ ## Allow incoming Flash Proxy connections on the external interface.
+ ## This has NOTHING to do with Adobe Flash.
+ ## DISABLED BY DEFAULT.
+ if [ "$GATEWAY_ALLOW_INCOMING_FLASHPROXY" = "1" ]; then
+ $iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --dport "$FLASHPROXY_PORT" -j ACCEPT
+ fi
+
+ local local_port_to_open
+ for local_port_to_open in $EXTERNAL_OPEN_PORTS; do
+ $iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --dport "$local_port_to_open" -j ACCEPT
+ done
+
+ local local_udp_port_to_open
+ for local_udp_port_to_open in $EXTERNAL_UDP_OPEN_PORTS; do
+ $iptables_cmd -A INPUT -p udp --dport "$local_udp_port_to_open" -j ACCEPT
+ done
+
+ if [ "$EXTERNAL_OPEN_ALL" = "true" ]; then
+ $iptables_cmd -A INPUT -j ACCEPT
+ fi
+ done
+
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true "timesync-fail-closed mode, skipping rest of function $FUNCNAME"
+ return 0
+ fi
+
+ for ext_if_item in $EXT_IF; do
+ ## Allow incoming DIRPORT connections for an optional Tor relay.
+ ## DISABLED BY DEFAULT.
+ if [ "$GATEWAY_ALLOW_INCOMING_DIR_PORT" = "1" ]; then
+ $iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --dport "$DIR_PORT" -j ACCEPT
+ fi
+
+ ## Allow incoming ORPORT connections for an optional Tor relay.
+ ## DISABLED BY DEFAULT.
+ if [ "$GATEWAY_ALLOW_INCOMING_OR_PORT" = "1" ]; then
+ $iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --dport "$OR_PORT" -j ACCEPT
+ fi
+
+ ## Custom Open Ports on external interface
+ ## - untested, should work
+ ## - Replace 22,9050,9051,9150,9151 with any ports you like to be open, example: 9050,9051
+ ## or just 9050
+ ## - $iptables_cmd v1.4.14: multiport needs -p tcp, -p udp, -p udplite, -p sctp or -p dccp
+ #$iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --match multiport --dports 22,9050,9051,9150,9151 -j ACCEPT
+ #$iptables_cmd -A INPUT -i "$ext_if_item" -p udp --match multiport --dports 22,9050,9051,9150,9151 -j ACCEPT
+
+ ## OPTIONAL Allow incoming OpenVPN connections on the external interface.
+ #$iptables_cmd -A INPUT -i "$ext_if_item" -p tcp --dport 1194 -j ACCEPT
+ done
+
+ local int_tif_item
+ local int_if_item
+
+ for int_tif_item in $INT_TIF; do
+ if [ "$WORKSTATION_TRANSPARENT_DNS" = "1" ]; then
+ ## Allow DNS traffic to DnsPort.
+ $iptables_cmd -A INPUT -i "$int_tif_item" -p udp --dport "$DNS_PORT_WORKSTATION" -j ACCEPT
+ fi
+ done
+
+ for int_if_item in $INT_IF; do
+ if [ "$WORKSTATION_TRANSPARENT_TCP" = "1" ]; then
+ ## Allow TCP traffic TransPort.
+ $iptables_cmd -A INPUT -i "$int_if_item" -p tcp --dport "$TRANS_PORT_WORKSTATION" -j ACCEPT
+ fi
+ done
+
+ for int_tif_item in $INT_TIF; do
+ ## Allow TCP traffic to Control Port Filter Proxy.
+ if [ "$CONTROL_PORT_FILTER_PROXY_ENABLE" = "1" ]; then
+ $iptables_cmd -A INPUT -i "$int_tif_item" -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" -j ACCEPT
+ fi
+
+ ## Allow socksified applications.
+ if [ "$WORKSTATION_ALLOW_SOCKSIFIED" = "1" ]; then
+ for socks_port in $socks_ports_list; do
+ true "$socks_port: ${!socks_port}"
+ $iptables_cmd -A INPUT -i "$int_tif_item" -p tcp --dport "${!socks_port}" -j ACCEPT
+ done
+
+ ## Accept ports 9152-9189 prepared for user custom applications.
+ ## See /usr/share/tor/tor-service-defaults-torrc for more comments.
+ $iptables_cmd -A INPUT -i "$int_tif_item" -p tcp --match multiport --dports 9152:9189 -j ACCEPT
+ fi
+ done
+
+ for int_if_item in $INT_IF; do
+ ## Redirect Control Port Filter Proxy to Control Port Filter Proxy port.
+ if [ "$CONTROL_PORT_FILTER_PROXY_ENABLE" = "1" ]; then
+ $iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -d "$WORKSTATION_DEST_SOCKSIFIED" -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" -j REDIRECT --to-ports "$CONTROL_PORT_FILTER_PROXY_PORT"
+ fi
+
+ if [ "$WORKSTATION_ALLOW_SOCKSIFIED" = "1" ]; then
+ for socks_port in $socks_ports_list; do
+ true "$socks_port: ${!socks_port}"
+ ## Redirect Browser/IRC/TorBirdy, etc. to SocksPort.
+ $iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -d "$WORKSTATION_DEST_SOCKSIFIED" -p tcp --dport "${!socks_port}" -j REDIRECT --to-ports "${!socks_port}"
+ done
+
+ ## Redirect ports 9152-9189 prepared for user custom applications.
+ $iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -d "$WORKSTATION_DEST_SOCKSIFIED" -p tcp --dport 9152:9189 -j REDIRECT
+ fi
+
+ if [ "$WORKSTATION_TRANSPARENT_DNS" = "1" ]; then
+ ## Redirect remaining DNS traffic to DNS_PORT_WORKSTATION.
+ ## Only user installed applications not configured to use a SocksPort are affected.
+ $iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -p udp --dport 53 -j REDIRECT --to-ports "$DNS_PORT_WORKSTATION"
+ fi
+
+ if [ "$WORKSTATION_TRANSPARENT_TCP" = "1" ]; then
+ ## Catch all remaining TCP and redirect to TransPort.
+ ## Only user installed applications not configured to use a SocksPort are affected.
+ $iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -p tcp --syn -j REDIRECT --to-ports "$TRANS_PORT_WORKSTATION"
+
+ ## Optionally restrict TransPort.
+ ## Replace above rule with a more restrictive one, e.g.:
+ #$iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -p tcp --match multiport --dports 80,443 --syn -j REDIRECT --to-ports "$TRANS_PORT_WORKSTATION"
+ fi
+ done
+}
+
+ipv4_input_defaults() {
+ ## Log.
+ #$iptables_cmd -A INPUT -j LOG --log-prefix "Whonix blocked input4: "
+
+ ## Reject anything not explicitly allowed above.
+ ## Drop is better than reject here, because we do not want to reveal it's a Whonix-Gateway.
+ ## (In case someone running Whonix-Gateway on bare metal.)
+ $iptables_cmd -A INPUT -j DROP
+}
+
+ipv4_forward() {
+ ## Log.
+ #$iptables_cmd -A FORWARD -j LOG --log-prefix "Whonix blocked forward4: "
+
+ ## Reject everything.
+ $iptables_cmd -A FORWARD -j REJECT --reject-with icmp-admin-prohibited
+}
+
+ipv4_reject_invalid_outgoing_packages() {
+ ## Drop invalid outgoing packages,
+ ## unless NO_REJECT_INVALID_OUTGOING_PACKAGES is set to 1.
+ if [ ! "$NO_REJECT_INVALID_OUTGOING_PACKAGES" = "1" ]; then
+ ## https://lists.torproject.org/pipermail/tor-talk/2014-March/032507.html
+ $iptables_cmd -A OUTPUT -m conntrack --ctstate INVALID -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -m state --state INVALID -j REJECT --reject-with icmp-admin-prohibited
+ #$iptables_cmd -A OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,FIN ACK,FIN -j REJECT --reject-with icmp-admin-prohibited
+ #$iptables_cmd -A OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,RST ACK,RST -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP INVALID SYN PACKETS
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags SYN,RST SYN,RST -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
+ $iptables_cmd -A OUTPUT -f -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP INCOMING MALFORMED XMAS PACKETS
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags ALL ALL -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP INCOMING MALFORMED NULL PACKETS
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags ALL NONE -j REJECT --reject-with icmp-admin-prohibited
+ fi
+}
+
+ipv4_output() {
+ lsmod | grep -q xt_owner || modprobe xt_owner
+
+ ## Allow outgoing traffic on VPN interface,
+ ## if VPN_FIREWALL mode is enabled.
+ ## DISABLED BY DEFAULT.
+ if [ "$VPN_FIREWALL" = "1" ]; then
+ $iptables_cmd -A OUTPUT -o "$VPN_INTERFACE" -j ACCEPT
+ fi
+
+ local no_nat_user
+ for no_nat_user in $NO_NAT_USERS ; do
+ $iptables_cmd -t nat -A OUTPUT -m owner --uid-owner "$no_nat_user" -j RETURN
+ done
+
+ if [ "$firewall_mode" = "full" ]; then
+ ## Redirect of Gateway DNS traffic to DNS_PORT_GATEWAY.
+ ## DISABLED BY DEFAULT. default. Using SocksPort instead.
+ if [ "$GATEWAY_TRANSPARENT_DNS" = "1" ]; then
+ $iptables_cmd -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports "$DNS_PORT_GATEWAY"
+ fi
+ fi
+
+ if [ "$firewall_mode" = "full" ]; then
+ ## Exclude connections to local network, Whonix-Workstation, VirtualBox from being redirected through Tor,
+ ## unless VPN_FIREWALL mode is enabled.
+ ## ENABLED BY DEFAULT.
+ if [ ! "$VPN_FIREWALL" = "1" ]; then
+ local non_tor_gateway_item
+ for non_tor_gateway_item in $NON_TOR_GATEWAY; do
+ $iptables_cmd -t nat -A OUTPUT -m iprange --dst-range "$non_tor_gateway_item" -j RETURN
+ done
+ fi
+ fi
+
+ if [ "$firewall_mode" = "full" ]; then
+ ## Redirect all Gateway TCP traffic to TRANS_PORT_GATEWAY.
+ ## DISABLED BY DEFAULT. Using SocksPort instead.
+ if [ "$GATEWAY_TRANSPARENT_TCP" = "1" ]; then
+ $iptables_cmd -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports "$TRANS_PORT_GATEWAY"
+ fi
+ fi
+
+ ## Existing connections are accepted.
+ $iptables_cmd -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
+
+ if [ "$firewall_mode" = "full" ]; then
+ ## Accept outgoing connections to local network, Whonix-Workstation and VirtualBox,
+ ## unless VPN_FIREWALL mode is enabled.
+ ## ENABLED BY DEFAULT.
+ if [ ! "$VPN_FIREWALL" = "1" ]; then
+ for non_tor_gateway_item in $NON_TOR_GATEWAY; do
+ $iptables_cmd -A OUTPUT -m iprange --dst-range "$non_tor_gateway_item" -j ACCEPT
+ done
+ fi
+ fi
+
+ if [ "$firewall_mode" = "full" ]; then
+ ## Accept outgoing connections to local network,
+ ## when VPN_FIREWALL mode is enabled.
+ ## DISABLED BY DEFAULT.
+ if [ "$VPN_FIREWALL" = "1" ]; then
+ local local_net_item
+ for local_net_item in $LOCAL_NET; do
+ $iptables_cmd -A OUTPUT -m iprange --dst-range "$local_net_item" -j ACCEPT
+ done
+ fi
+ fi
+
+ ## Prevent connections to Tor SocksPorts.
+ ## https://phabricator.whonix.org/T533#11025
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ local socks_port_item
+ for socks_port_item in $socks_ports_list; do
+ true "$socks_port_item: ${!socks_port_item}"
+ if [ "$SOCKS_PORT_SDWDATE" = "${!socks_port_item}" ]; then
+ continue
+ fi
+ $iptables_cmd -A OUTPUT -p tcp --dport "${!socks_port_item}" --dst "127.0.0.1" -j REJECT
+ done
+ fi
+
+ ## Access to localhost is required even in timesync-fail-closed mode,
+ ## otherwise breaks applications such as konsole and kwrite.
+ $iptables_cmd -A OUTPUT -o lo -j ACCEPT
+
+ for no_nat_user in $NO_NAT_USERS ; do
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$no_nat_user" -j ACCEPT
+ done
+
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ ## Allow sdwdate talking to localhost and Tor in Whonix firewall timesync-fail-closed mode.
+ ## Otherwise in Whonix firewall full mode this rule is redundant.
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "127.0.0.1" -j ACCEPT
+ fi
+
+ ## Log.
+ #$iptables_cmd -A OUTPUT -j LOG --log-prefix "Whonix blocked output4: "
+
+ ## Reject all other outgoing traffic.
+ $iptables_cmd -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
+}
+
+ipv6() {
+ ## Policy DROP for all traffic as fallback.
+ $ip6tables_cmd -P INPUT DROP
+ $ip6tables_cmd -P OUTPUT DROP
+ $ip6tables_cmd -P FORWARD DROP
+
+ ## Flush old rules.
+ $ip6tables_cmd -F
+ $ip6tables_cmd -X
+ $ip6tables_cmd -t mangle -F
+ $ip6tables_cmd -t mangle -X
+
+ ## Allow unlimited access on loopback.
+ ## Not activated, since we do not need it.
+ #$ip6tables_cmd -A INPUT -i lo -j ACCEPT
+ #$ip6tables_cmd -A OUTPUT -o lo -j ACCEPT
+
+ ## Log.
+ #$ip6tables_cmd -A INPUT -j LOG --log-prefix "Whonix blocked input6: "
+ #$ip6tables_cmd -A OUTPUT -j LOG --log-prefix "Whonix blocked output6: "
+ #$ip6tables_cmd -A FORWARD -j LOG --log-prefix "Whonix blocked forward6: "
+
+ ## Drop/reject all other traffic.
+ $ip6tables_cmd -A INPUT -j DROP
+ ## --reject-with icmp-admin-prohibited not supported by ip6tables
+ $ip6tables_cmd -A OUTPUT -j REJECT
+ ## --reject-with icmp-admin-prohibited not supported by ip6tables
+ $ip6tables_cmd -A FORWARD -j REJECT
+}
+
+status_files() {
+ mkdir --parents /run/whonix_firewall
+ if [ -e /run/whonix_firewall/first_run_current_boot.status ]; then
+ touch /run/whonix_firewall/consecutive_run.status
+ return 0
+ fi
+ touch /run/whonix_firewall/first_run_current_boot.status
+}
+
+date_cmd(){
+ date -u +"%Y-%m-%d %T"
+}
+
+output_cmd() {
+ echo "$(date_cmd) - $0 - $@"
+}
+
+firewall_mode_detection() {
+ if [ ! "$firewall_mode" = "" ]; then
+ output_cmd "OK: Skipping firewall mode detection since already set to '$firewall_mode'."
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ output_cmd "OK: (Only local Tor control port connections and torified sdwdate allowed.)"
+ return 0
+ elif [ "$firewall_mode" = "full" ]; then
+ output_cmd "OK: (Full torified network access allowed.)"
+ return 0
+ else
+ output_cmd "ERROR: firewall_mode must be set to either 'full' or 'timesync-fail-closed'."
+ error_handler
+ fi
+ fi
+
+ ## Run Whonix firewall in full mode if sdwdate already succeeded.
+ if [ -e /run/sdwdate/first_success ]; then
+ firewall_mode=full
+ output_cmd "OK: (/run/sdwdate/first_success exists.)"
+ elif [ -e /run/sdwdate/success ]; then
+ firewall_mode=full
+ output_cmd "OK: (/run/sdwdate/success exists.)"
+ ## /run/whonix_firewall/first_run_current_boot.status already exists,
+ ## therefore have Whonix firewall run in full mode.
+ elif [ -e /run/whonix_firewall/first_run_current_boot.status ]; then
+ firewall_mode=full
+ output_cmd "OK: (/run/whonix_firewall/first_run_current_boot.status exists.)"
+ else
+ ## /run/whonix_firewall/first_run_current_boot.status does not yet exist,
+ ## therefore return 'yes, timesync-fail-closed'.
+ firewall_mode=timesync-fail-closed
+ fi
+
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ output_cmd "OK: First run during current boot, therefore running in timesync-fail-closed mode."
+ output_cmd "OK: (Only local Tor control port connections and torified sdwdate allowed.)"
+ else
+ output_cmd "OK: Consecutive run during current boot, therefore running in full mode."
+ output_cmd "OK: (Full torified network access allowed.)"
+ fi
+}
+
+end() {
+ output_cmd "OK: Whonix firewall loaded."
+
+ exit 0
+}
+
+main() {
+ init
+ firewall_mode_detection
+ variables_defaults
+ ipv4_defaults
+ ipv4_preparation
+ ipv4_drop_invalid_incoming_packages
+ qubes
+ ipv4_input_rules
+ ipv4_input_defaults
+ ipv4_forward
+ ipv4_reject_invalid_outgoing_packages
+ ipv4_output
+ if [ -d /proc/sys/net/ipv6/ ]; then
+ ipv6
+ fi
+ status_files
+ end
+}
+
+source_config_folder
+main
diff --git a/overlay/Linux/usr/local/sbin/proxy_firewall_start.bash b/overlay/Linux/usr/local/sbin/proxy_firewall_start.bash
new file mode 100755
index 0000000..5a8c4b3
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_firewall_start.bash
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+ROLE=proxy
+. /usr/local/bin/proxy_ping_lib.bash || { echo ERROR: loading /usr/local/bin/proxy_ping_lib.bash ; exit 3; }
+proxy_ping_firewall_restart $*
diff --git a/overlay/Linux/usr/local/sbin/proxy_libvirt_ga_test.bash b/overlay/Linux/usr/local/sbin/proxy_libvirt_ga_test.bash
new file mode 100755
index 0000000..6cb3bde
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_libvirt_ga_test.bash
@@ -0,0 +1,80 @@
+#!/bin/sh
+# -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=hostvms
+
+#[ $# -eq 0 ] && set -- Whonix-Gateway /bin/cat /proc/cmdline
+[ $# -eq 0 ] && set -- Whonix-Gateway /bin/netstat -lnp4
+[ $# -lt 2 ] && echo USAGE: $0 domain command arguments
+. /usr/local/bin/usr_local_tput.bash || exit 3
+
+HOST=$1
+shift
+CMD=$1
+shift
+
+# FixMe
+if [ $# -lt 1 ] ; then
+ ARGS=""
+ elif [ $# -gt 1 ] ; then
+ ARGS=`sed -e 's/ /","/g' <<< $*`
+ else
+ ARGS="$1"
+fi
+
+[ "$HOST" = WWork106 ] && HOST=Whonix-Workstation || true
+[ "$HOST" = WGate106 ] && HOST=Whonix-Gateway || true
+[ -z "$CMD" ] && CMD=/usr/sbin/qemu-ga && ARGS=-D
+
+INFO $0 $HOST $CMD $ARGS
+
+if ifconfig virbr1 | grep -q 10.0.2.2 ; then
+ # lrwxrwxrwx 1 root root 11 Aug 26 21:58 /dev/virtio-ports/org.qemu.guest_agent.0 -> ../vport3p2
+ INFO ssh user@10.0.2.15 virbr1
+ ssh user@10.0.2.15 ls -l /dev/virtio-ports/org.qemu.guest_agent.0 | \
+ grep /dev/virtio-ports/org.qemu.guest_agent.0 || \
+ WARN NOT ssh ls -l /dev/virtio-ports/org.qemu.guest_agent.0
+ # /usr/sbin/qemu-ga
+ ssh user@10.0.2.15 ps ax | \
+ grep qemu-ga || \
+ WARN NOT ssh ps qemu-ga
+fi
+
+
+DBUG virsh qemu-agent-command $HOST \
+ '{"execute":"guest-exec", "arguments": {"capture-output": true,"path":"'$CMD'","arg":["'$ARGS'"]}}'
+virsh qemu-agent-command $HOST \
+ '{"execute":"guest-exec", "arguments": {"capture-output": true,"path":"'$CMD'","arg":["'$ARGS'"]}}' \
+ >/tmp/Q$$.out || exit 1$?
+
+grep -q return /tmp/Q$$.out || exit 2
+pid=`sed -e 's/.*://' -e 's/}.*//' /tmp/Q$$.out`
+[ $? -eq 0 -a -n "$pid" ] || exit 3
+
+# DBUG virsh qemu-agent-command $HOST \
+# '{"execute":"guest-exec-status", "arguments": {"pid": '$pid'}}'
+#virsh qemu-agent-command $HOST \
+# '{"execute":"guest-exec-status", "arguments": {"pid": '$pid'}}' \
+# >/tmp/R$$.out || exit 4$?
+
+TRIES=10
+i=0
+while [ $i -lt $TRIES ] ; do
+ i=`expr $i + 1`
+ virsh qemu-agent-command $HOST \
+ '{"execute":"guest-exec-status", "arguments": {"pid": '$pid'}}' \
+ >/tmp/R$$.out || exit 4$i$?
+ grep -q '"exitcode":0' /tmp/R$$.out && break
+ sleep 5
+ DBUG $i
+done
+[ $i -lt $TRIES ] || \
+ { ERROR $i no exitcode in /tmp/R$$.out; exit 5 ; }
+
+b64=`sed -e 's/{"return":{"exitcode":0,"out-data":"//' -e 's/",".*//' /tmp/R$$.out`
+[ $? -eq 0 ] || exit 6
+[ -n "$b64" ] || exit 7
+echo $b64 | base64 -d - || exit 8
+
+rm -f /tmp/{Q,R}$$.out
+exit 0
diff --git a/overlay/Linux/usr/local/sbin/proxy_libvirt_hook_network.bash b/overlay/Linux/usr/local/sbin/proxy_libvirt_hook_network.bash
new file mode 100755
index 0000000..9332d15
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_libvirt_hook_network.bash
@@ -0,0 +1,29 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+prog=$( basename $0 .bash )
+PREFIX=/usr/local
+ROLE=proxy
+. /usr/local/bin/usr_local_tput.bash
+
+. /usr/local/bin/proxy_ping_lib.bash || exit 1$?
+
+if [ -f /etc/modules-load.d/firewall.conf ] ; then
+ grep -v '#' /etc/modules-load.d/firewall.conf|xargs modprobe --all
+fi
+
+proxy_ping_firewall_restart
+retval=$?
+if [ $retval -eq 0 ] ; then
+ logger INFO: $prog proxy_ping_firewall_restart $*
+ else
+ logger ERROR: $prog proxy_ping_firewall_restart retval=$retval $*
+ exit $retval
+fi
+
+# clean
+exit 0
+
+# BEGIN ANSIBLE MANAGED BLOCK proxy whonix_host.yml
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+# END ANSIBLE MANAGED BLOCK proxy whonix_host.yml
diff --git a/overlay/Linux/usr/local/sbin/proxy_libvirt_hook_qemu.bash b/overlay/Linux/usr/local/sbin/proxy_libvirt_hook_qemu.bash
new file mode 100755
index 0000000..2295b9c
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_libvirt_hook_qemu.bash
@@ -0,0 +1,13 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+prog=$( basename $0 .bash )
+PREFIX=/usr/local
+ROLE=proxy
+
+. /usr/local/bin/usr_local_tput.bash
+
+logger INFO: $0 $PWD $*
+
+exit 0
+
diff --git a/overlay/Linux/usr/local/sbin/proxy_tor_lib.bad b/overlay/Linux/usr/local/sbin/proxy_tor_lib.bad
new file mode 100755
index 0000000..12ed9f8
Binary files /dev/null and b/overlay/Linux/usr/local/sbin/proxy_tor_lib.bad differ
diff --git a/overlay/Linux/usr/local/sbin/proxy_tor_lib.bash b/overlay/Linux/usr/local/sbin/proxy_tor_lib.bash
new file mode 100755
index 0000000..7e4dc73
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_tor_lib.bash
@@ -0,0 +1,217 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+## /usr/local/bin/proxy_whonix_tor_start.bash
+
+ROLE=proxy
+[ -z "$prog" ] && prog=$( basename $0 .bash )
+[ -z "$PRIV_TOR_OWNER" ] && grep -q ^debian-tor /etc/passwd && PRIV_TOR_OWNER=debian-tor
+
+## host_tor_verify_config
+. /usr/local/bin/usr_local_tput.bash || exit 3
+host_tor_verify_config () {
+ # tor --verify-config # || exit 2$?
+ su -c 'tor --verify-config' -s /bin/sh $PRIV_TOR_OWNER \
+ | grep -v 'notice\|DisableNetwork'
+ # || exit 2
+ return 0
+}
+
+tor_grep_log () {
+ local log
+
+ [ -f /run/tor/log ] && log=/run/tor/log || log=/tmp/tor.log
+ [ -f $log ] || { WARN $prog $log not found ; return 1 ; }
+
+ INFO grep % $log
+ grep % $log | grep -v 5%
+
+ return 0
+}
+
+## host_tor_is_running
+host_tor_is_running () {
+ local retval
+
+ retval=0
+ if netstat -nlp4 2>&1| grep ':90.*/tor' ; then
+ DBUG $prog tor is already running
+ retval=2
+ elif ps ax | grep -v grep | grep "su -c tor -s /bin/sh $PRIV_TOR_OWNER" ; then
+ DBUG $prog tor is already running
+ retval=3
+ elif ls -l /run/tor/socket 2>/dev/null ; then
+ DBUG $prog tor is already running
+ retval=4
+ fi
+ tor_grep_log
+ return $retval
+}
+
+## host_tor_start
+host_tor_start () {
+ #su -c '/etc/init.d/tor stop' -s /bin/sh $PRIV_TOR_OWNER
+ #sleep 5
+
+ [ -d /run/tor/ ] && rm -f /run/tor/* || mkdir /run/tor
+ # systemd overrides these
+ chown $PRIV_TOR_OWNER.$PRIV_TOR_OWNER /run/tor
+ chmod 2750 /run/tor/
+
+ gateway_tor_stop
+ # systemctl daemon-reload
+ rm -f /run/tor/log.err /tmp/log.err
+ rm -f /run/tor/log /tmp/log.log
+ rm -f /run/tor/tor.pid /tmp/log.pid
+
+
+ INFO starting tor - see /tmp/tor.err /tmp/tor.log
+
+ if false ; then
+ su -c '/etc/init.d/tor start' -s /bin/sh $PRIV_TOR_OWNER
+ netstat -nlp -t inet | grep "$IP:9128" || systemctl --no-pager restart tor@default || return 4$?
+else
+ su -c 'tor' -s /bin/sh $debian 2>/tmp/tor.err >/tmp/tor.log &
+ echo -n $! >/tmp/tor.pid
+fi
+ sleep 15
+
+ return 0
+}
+
+## host_tor_stop
+host_tor_stop () {
+ local debian
+
+ [ -s /tmp/tor.pid ] && \
+ DBUG $prog kill $( cat /tmp/tor.pid ) && \
+ kill $( cat /tmp/tor.pid ) 2>/dev/null && \
+ rm /tmp/tor.pid
+ rm -f /tmp/tor.log /tmp/tor.err
+ debian=$PRIV_TOR_OWNER
+ pkill -u $debian
+ [ -s /tmp/tog.pid ] && \
+ kill $( cat /tmp/tog.pid ) 2>/dev/null \
+ && rm /tmp/tog.pid
+ # echo 1|sudo dd of=/proc/sys/net/ipv4/tcp_tw_reuse
+ return 0
+}
+
+PROXY_ExcludeNodes="{gb},{ca}"
+
+## proxy_tor_torrc_update
+proxy_tor_torrc_update () {
+ local file IP
+ file=$1
+ IP=$2
+ grep -q "SocksPort $IP:9050" $file || \
+ echo "SocksPort $IP:9050" >> $file
+ grep -q "DNSPort $IP:9053" $file || \
+ echo "DNSPort $IP:9053" >> $file
+ if false ; then
+ grep -q "TransPort $IP:9040" $file || \
+ echo "TransPort $IP:9040 IsolateClientAddr IsolateClientProtocol IsolateDestAddr IsolateDestPort" >> $file
+ fi
+ grep -q "HTTPTunnelPort $IP:9128" $file || \
+ echo "HTTPTunnelPort $IP:9128 IsolateDestAddr" >> $file
+ return 0
+}
+
+
+export TOR_LOG="/var/log/tor/log"
+export TOR_DIR=/var/lib/tor/data
+
+cmd_item_list=(
+"--has-consensus"
+"--current-time-in-valid-range"
+"--show-valid-after"
+"--show-valid-until"
+"--show-middle-range"
+)
+
+#"--tor-cert-lifetime-invalid"
+#"--tor-cert-valid-after"
+
+## proxy_tor_test_ntp
+proxy_tor_test_ntp () {
+ /usr/local/bin/proxy_ping_test.bash ntp
+ return $?
+}
+
+## proxy_tor_test_anondate
+proxy_tor_test_anondate () {
+ local cmd_item outout exit_code
+
+for cmd_item in ${cmd_item_list[@]} ; do
+ output="$( /usr/local/lib/helper-scripts/anondate $cmd_item $@ )"
+ exit_code="$?"
+ if [ $exit_code -eq 0 ] ; then
+ INFO "/usr/local/lib/helper-scripts/anondate $cmd_item $@"
+ echo "output: $output"
+ else
+ echo "WARN: /usr/local/lib/helper-scripts/anondate $cmd_item $@"
+ echo -n "exit_code: $exit_code "
+ echo "output: $output"
+ fi
+done
+ return 0
+}
+
+host_tor_status () {
+ [ -f /tmp/tor.pid ] && \
+ [ $( wc -c /tmp/tor.pid|sed -e 's/ .*//' ) -le 1 ] && \
+ rm /tmp/tor.pid
+
+ if [ -f /tmp/tor.pid ]; then
+ ps -p "$( cat /tmp/tor.pid )"
+ elif [ -f /run/tor/tor.pid ] ; then
+ ps -p "$( cat /run/tor/tor.pid )"
+ else
+ WARN $prog no /tmp/tor.pid or /run/tor/tor.pid
+ fi
+
+ [ ! -f /usr/local/src/helper-scripts/tor_bootstrap_check.py ] || \
+ python3 /usr/local/src/helper-scripts/tor_bootstrap_check.py \
+ || return 1
+
+ debian=$PRIV_TOR_OWNER
+ INFO $prog $debian processes:
+ ps -g $debian
+
+ guest_qemu_status || return 2$?
+ tor_start_not_running && return 3$?
+
+ [ ! -f /usr/local/src/helper-scripts/tor_circuit_established_check.py ] || \
+ a=$( python3 /usr/local/src/helper-scripts/tor_circuit_established_check.py ) \
+ || return 4
+ [ "$a" = "1" ]|| { echo "WARN: $prog tor_circuit_established_check != 1" ;
+ return 5
+ }
+
+ return 0
+}
+
+## proxy_tor_torrc_exclude
+proxy_tor_torrc_exclude () {
+ local file
+ [ $# -eq 0 ] && file=$1 || file=/etc/tor/torrc
+ [ -n "$file" ] || return 1
+ [ -f "$file" ] || return 2
+ [ -n "$PROXY_ExcludeNodes" ] || return 3
+ grep -q "ExcludeNodes.*$PROXY_ExcludeNodes" "$file" && return 0
+ if grep -q "ExcludeNodes" $file ; then
+ sed -e "s@ExcludeNodes.*@ExcludeNodes ${PROXY_ExcludeNodes}@" -i $file
+ else
+ echo "ExcludeNodes $PROXY_ExcludeNodes" >> $file
+ fi
+
+ return 0
+}
+
+base=proxy_tor_lib
+if [ -x /usr/bin/basename ] && [ $( /usr/bin/basename -- $0 ) = $base'.bash' -o $( basename -- $0 ) = $base'.sh' ] ; then
+ [ "$#" -eq 0 ] && exit 0
+ [ "$#" -eq 1 ] && [ "$1" = '-h' -o "$1" = '--help' ] && echo USAGE: $0 && grep '^[a-z].*()\|^## ' $0 | sed -e 's/().*//'|sort && exit 0
+ eval "$@"
+ exit $?
+ fi
+
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix-libvirt-install.bash b/overlay/Linux/usr/local/sbin/proxy_whonix-libvirt-install.bash
new file mode 100755
index 0000000..b64580c
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix-libvirt-install.bash
@@ -0,0 +1,172 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+set -o pipefail || exit 1
+
+# was in /usr/lib/whonix-libvirt/install
+# unlike that one, this should be idempotent
+# [ -f /var/lib/whonix-libvirt/install.done ] && exit 0
+
+prog=$( basename $0 .bash )
+PREFIX=/usr/local
+ROLE=base
+. /usr/local/bin/usr_local_tput.bash
+
+GATEW=1
+# for testforge use we only need the Gateway
+WORKS=
+
+[ -f $PREFIX/etc/testforge/testforge.bash ] && . /usr/local/etc/testforge/testforge.bash
+. /usr/local/bin/proxy_ping_lib.bash || \
+ { echo ERROR: loading /usr/local/bin/proxy_ping_lib.bash ; exit 1; }
+. /usr/local/bin/usr_local_base.bash || exit 2
+
+MODE=`proxy_ping_mode`
+[ $MODE = whonix ] || exit 0
+
+#? echo ERROR: avoiding $prog proxy_whonix-libvirt-install.bash ; exit 10
+
+[ -x /usr/local/bin/proxy_libvirt_hook_network.bash ] || exit 12
+/usr/local/bin/proxy_libvirt_hook_network.bash || exit 13
+
+[ -d /usr/local/var/log ] || mkdir /usr/local/var/log || exit 14
+chmod 1777 /usr/local/var/log
+
+[ -f /etc/firewall.conf.whonix ] || \
+ cp -p /usr/local/etc/firewall.conf.* /etc/ || exit 15
+
+[ -f /etc/firewall.conf ] || \
+ cp -p /etc/firewall.conf.whonix /etc/firewall.conf || exit 16
+
+# ERROR: proxy_ping_firewall_check /etc/firewall.conf empty
+[ -x /etc/libvirt/hooks/network ] || cat > /etc/libvirt/hooks/network << \EOF
+#!/bin/sh
+[ -d /usr/local/var/log ] || mkdir /usr/local/var/log
+echo INFO: hooks/network $* > /usr/local/var/log/libvirt_network.log
+bash /usr/local/bin/proxy_libvirt_hook_network.bash "$@" \
+ >> /usr/local/var/log/libvirt_network.log 2>&1
+EOF
+[ -x /etc/libvirt/hooks/network ] || chmod a+x /etc/libvirt/hooks/network
+ /etc/libvirt/hooks/network || exit 16
+
+## Copyright (C) 2019 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+set -e
+
+## {{ Taken from qemu-system-common.postinst.
+# Add the kvm group unless it's already there
+if ! getent group kvm >/dev/null; then
+ addgroup --quiet --system kvm || true
+fi
+## }} Taken from qemu-system-common.postinst.
+
+## {{ Taken from libvirt-bin.postinst.
+if ! getent group libvirt >/dev/null; then
+ addgroup --system libvirt
+fi
+## }} Taken from libvirt-bin.postinst.
+
+## Existence of user "user" is not guaranteed at this point.
+if grep -q ^user /etc/passwd ; then
+ grep -q ^kvm /etc/group || addgroup user kvm
+ grep -q ^libvirt /etc/group || addgroup user libvirt
+fi
+
+## Create shared directory and adjust permissions
+[ -d /mnt/gateway-shared ] || mkdir --parents /mnt/gateway-shared
+[ -n "$WORKS" ] && [ -d /mnt/workstation-shared ] || mkdir --parents /mnt/workstation-shared
+chmod 1777 /mnt/gateway-shared
+[ -n "$WORKS" ] && chmod 1777 /mnt/workstation-shared
+
+
+## networks
+proxy_virsh net-list --all | grep -q default || \
+ virsh -c qemu:///system net-autostart "default" || exit 1$?
+#? virsh -c qemu:///system net-start "default" || exit 2$?
+proxy_virsh net-list --all | grep -q Whonix-External || \
+ virsh -c qemu:///system net-define "/usr/local/etc/libvirt/qemu/networks/Whonix-External.xml" \
+ || exit 3$?
+proxy_virsh net-list --all | grep -q Whonix-Internal || \
+ virsh -c qemu:///system net-define "/usr/local/etc/libvirt/qemu/networks/Whonix-Internal.xml" \
+ || exit 4$?
+
+#no virsh -c qemu:///system net-autostart "Whonix-External"
+proxy_virsh net-list | grep -q Whonix-External || \
+ virsh -c qemu:///system net-start "Whonix-External" || exit 5$?
+# no virsh -c qemu:///system net-autostart "Whonix-Internal"
+proxy_virsh net-list | grep -q Whonix-Internal || \
+ virsh -c qemu:///system net-start "Whonix-Internal" || exit 6$?
+
+lsmod | grep -q kvm||modprobe kvm || exit 7
+temp_dir=/usr/local/etc/libvirt/qemu
+
+if virsh capabilities | grep -q "/dev/null && \
+ rm /tmp/tor.pid
+ rm -f /tmp/tor.log /tmp/tor.err
+ debian=$PRIV_TOR_OWNER
+ pkill -u $debian
+ [ -s /tmp/tog.pid ] && \
+ kill $( cat /tmp/tog.pid ) 2>/dev/null \
+ && rm /tmp/tog.pid
+ systemctl stop vanguards
+ # systemctl start onion-grater >/dev/null && systemctl stop onion-grater
+ # echo 1|sudo dd of=/proc/sys/net/ipv4/tcp_tw_reuse
+ netstat -npet4
+
+ return 0
+}
+
+## gateway_tor_torrc
+gateway_tor_torrc () {
+ local file IP
+ # file=/etc/torrc.d/50_user.conf
+ file=/usr/local/etc/torrc.d/50_user.conf
+ if [ ! -f $file ] ; then
+ cat > $file <> $file
+ done
+ return 0
+}
+
+## gateway_tor_init_check_iptables
+gateway_tor_init_check_iptables () {
+ local rule changed
+ changed=0
+ rule='-A INPUT -i eth0 -p udp -m udp --dport 9053 -j ACCEPT'
+ if ! proxy_iptables_save | grep -q -e "$rule" ; then
+ [ $changed -eq 0 ] && proxy_iptables -D INPUT -j DROP
+ proxy_iptables $rule
+ changed=1
+ fi
+ rule='-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT'
+ if ! proxy_iptables_save | grep -q -e "$rule" ; then
+ [ $changed -eq 0 ] && proxy_iptables -D INPUT -j DROP
+ proxy_iptables $rule
+ changed=1
+ fi
+ rule='-A INPUT -i eth0 -p tcp -m tcp --dport 9128 -j ACCEPT'
+ if ! proxy_iptables_save | grep -q -e "$rule" ; then
+ [ $changed -eq 0 ] && proxy_iptables -D INPUT -j DROP
+ proxy_iptables $rule
+ changed=1
+ fi
+ [ $changed -gt 0 ] && proxy_iptables -A INPUT -j DROP
+ return 0
+}
+# systemctl --no-pager status tor@default
+
+## tor_start_not_running
+tor_start_not_running () {
+ local retval
+
+ retval=0
+ if netstat -nlp4 2>&1| grep '15:90.*/tor' ; then
+ DBUG $prog tor is already running
+ retval=2
+ elif ps ax | grep -v grep | grep "su -c tor -s /bin/sh $PRIV_TOR_OWNER" ; then
+ DBUG $prog tor is already running
+ retval=3
+ elif ls -l /run/tor/socket 2>/dev/null ; then
+ DBUG $prog tor is already running
+ retval=4
+ fi
+ tor_grep_log
+ return $retval
+}
+
+## gateway_tor_config_tor
+gateway_tor_config_tor () {
+
+ gateway_tor_init_check_iptables || exit 2$?
+ gateway_tor_torrc
+ gateway_tor_init_config_gateway_conf
+ rm -f /usr/local/etc/torrc.d/*~
+ return $?
+}
+
+## tor_start_verify_config
+tor_start_verify_config () {
+ # tor --verify-config # || exit 2$?
+ su -c 'tor --verify-config' -s /bin/sh $PRIV_TOR_OWNER \
+ | grep -v 'notice\|DisableNetwork'
+ # || exit 2
+ return 0
+}
+
+## tor_prepare_to_start
+tor_prepare_to_start () {
+ #su -c '/etc/init.d/tor stop' -s /bin/sh $PRIV_TOR_OWNER
+ #sleep 5
+
+ [ -d /run/tor/ ] && rm -f /run/tor/* || mkdir /run/tor
+ # systemd overrides these
+ chown $PRIV_TOR_OWNER.$PRIV_TOR_OWNER /run/tor
+ chmod 0700 /run/tor/
+
+ gateway_tor_stop
+ # systemctl daemon-reload
+ rm -f /run/tor/log.err /tmp/log.err
+ rm -f /run/tor/log /tmp/log.log
+ rm -f /run/tor/tor.pid /tmp/log.pid
+
+ sed '/DisableNetwork/d' -i /usr/local/etc/torrc.d/50_user.conf
+
+ return 0
+}
+
+## tor_after_start
+tor_after_start () {
+
+ [ -s /tmp/tor.err ] && ERROR $prog /tmp/tor.err && cat /tmp/tor.err && return 6
+ grep '\[warn\]' /tmp/tor.log
+ grep '\[err\]' /tmp/tor.log && ERROR $prog /tmp/tor.log && return 7
+
+ ls /run/tor/log* >/dev/null && \
+ sed -e '/configured a non-loopback address/d' -i /run/tor/log*
+ chmod 750 /run/tor/
+ chmod 640 /run/tor/log
+ INFO checked /tmp/tor.log /tmp/tor.err
+
+ INFO starting onion-grater
+ # systemctl start onion-grater
+ pidof /usr/lib/onion-grater || return 0
+ /usr/lib/onion-grater --listen-interface eth1 &
+ echo -n $! >/tmp/tog.pid
+ return 0
+}
+
+tor_grep_log () {
+ local log
+
+ [ -f /run/tor/log ] && log=/run/tor/log || log=/tmp/tor.log
+ [ -f $log ] || { WARN $prog $log not found ; return 1 ; }
+
+ INFO grep % $log
+ grep % $log | grep -v 5%
+
+ return 0
+}
+
+tor_test () {
+ tor_grep_log
+ tor_qemu_status || return 1$?
+ return 0
+}
+
+tor_qemu_status () {
+ local pid
+
+ pid=$( pidof /usr/sbin/qemu-ga )
+ [ $? -eq 0 -a -n "$pid" ] || \
+ { WARN $prog qemu-qa not running; return 1 ; }
+ lsof -p $pid | grep -q /dev/v || \
+ { WARN /usr/sbin/qemu-ga not bound to /dev ; return 1 ; }
+
+ return 0
+}
+
+tor_status () {
+ [ -f /tmp/tor.pid ] && \
+ [ $( wc -c /tmp/tor.pid|sed -e 's/ .*//' ) -le 1 ] && \
+ rm /tmp/tor.pid
+
+ if [ -f /tmp/tor.pid ]; then
+ ps -p "$( cat /tmp/tor.pid )"
+ elif [ -f /run/tor/tor.pid ] ; then
+ ps -p "$( cat /run/tor/tor.pid )"
+ else
+ WARN $prog no /tmp/tor.pid or /run/tor/tor.pid
+ fi
+
+ [ ! -f /usr/local/src/helper-scripts/tor_bootstrap_check.py ] || \
+ python3 /usr/local/src/helper-scripts/tor_bootstrap_check.py \
+ || return 1
+
+ debian=$( grep -q ^$PRIV_TOR_OWNER /etc/passwd && echo $PRIV_TOR_OWNER || echo tor )
+ INFO $prog $debian processes:
+ ps -g $debian
+
+ tor_qemu_status || return 1$?
+ tor_start_not_running && return 2$?
+
+ # /usr/lib/helper-scripts/tor_circuit_established_check.py
+
+ return 0
+}
+
+gateway_tor_verify () {
+ tor_start_verify_config || return 1
+
+ return 0
+}
+
+gateway_tor_start () {
+ local debian
+ # Nov 09 21:00:27 host vanguards[715]: WARNING[Mon Nov 09 21:00:27 2020]: Tor daemon connection failed: [Errno 24] Too many open files. Trying again...
+
+ # debian-tor soft nofile 100000
+ # /etc/security/limits.conf
+
+ gateway_tor_config_tor || return 2$?
+ tor_start_not_running || return 3$?
+
+ gateway_tor_verify || return 4$?
+ tor_prepare_to_start
+
+ INFO startiing tor - see /tmp/tor.err /tmp/tor.log
+ #su -c '/etc/init.d/tor start' -s /bin/sh $PRIV_TOR_OWNER
+ #netstat -nlp -t inet | grep "$IP:9128" || systemctl --no-pager restart tor@default || return 4$?
+ su -c 'tor' -s /bin/sh $PRIV_TOR_OWNER 2>/tmp/tor.err >/tmp/tor.log &
+ echo -n $! >/tmp/tor.pid
+
+ sleep 15
+
+ tor_after_start
+ tor_status
+ return 0
+}
+
+if [ "$#" -eq 0 ] ; then
+ echo USAGE: $prog "$USAGE"
+
+elif [ "$d1#" = '--help' ] ; then
+ echo USAGE: $prog "$USAGE" or:
+ grep '^## ' $0 | sed -e 's/^## //'
+
+ ## config
+ elif [ $1 = config ] ; then
+ INFO $prog $1
+ gateway_tor_config_tor || exit 1$?
+
+ ## stop -
+ elif [ $1 = stop ] ; then
+ INFO $prog $1
+ gateway_tor_stop
+ exit $?
+
+ ## status
+ elif [ $1 = status ] ; then
+ INFO $prog tor_status
+ tor_status || exit $?
+ exit 0
+
+ ## start
+ elif [ "$1" = gateway -o "$1" = start ] ; then
+ INFO $prog tor_start
+ gateway_tor_start
+ exit $?
+
+ ## restart
+ elif [ "$1" = restart ] ; then
+ INFO $prog tor_restart
+ gateway_tor_stop || exit 1$?
+ sleep 2
+ gateway_tor_start
+ exit $?
+
+ ## verify
+ elif [ "$1" = verify ] ; then
+ tor_start_verify_config
+
+ elif [ "$1" = test ] ; then
+ tor_test
+
+ elif [ "$1" = '--help' -o "$1" = '-h' ] ; then
+ echo USAGE: $prog "$USAGE or:"
+ grep '^## ' $0 | sed -e 's/## //'
+
+ else
+ eval "$@" || exit $?
+fi
+
+exit 0
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_guest_gateway.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_gateway.bash
new file mode 100755
index 0000000..e9e2041
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_gateway.bash
@@ -0,0 +1,262 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=proxy
+CONN=guest
+USAGE="[config|start|stop|test|verify]"
+prog=$( basename $0 .bash )
+. /usr/local/bin/usr_local_tput.bash
+
+. /usr/local/sbin/proxy_whonix_lib.bash || \
+ { ERROR loading /usr/local/sbin/proxy_whonix_lib.bash ; exit 1; }
+. /usr/local/sbin/proxy_whonix_gateway_tor.bash || \
+ { ERROR loading /usr/local/sbin/proxy_whonix_gateway_tor.bash ; exit 2; }
+. /usr/local/bin/usr_local_tput.bash || exit 3
+
+NSL='nslookup -querytype=A'
+NETS='netstat -nl4e'
+SHARED_MNTS="o"
+# ELTS="onion-grater" # these work and start normally
+# sdwdate should be linked to NetManager and prevents logins if not connected
+# well start tor ourselves
+# we dont need vanguards
+DISABLE_SERVICES="sdwdate tor vanguards"
+DISABLE_X_SERVICES="rads sdwdate-gui-shutdown-notify tor-control-panel"
+grep -q ' text ' /proc/cmdline && \
+ DISABLE_SERVICES="$DISABLE_X_SERVICES $DISABLE_SERVICES"
+
+## proxy_gateway_fix_getty_timeout
+proxy_gateway_fix_getty_timeout () {
+ # fix_getty_timeout - wheres inittab
+ grep -l '^Exec.*agetty -o' /lib/systemd/system/*service | while read file ; do
+ [ -f $file.dst ] && continue
+ cp -p $file $file.dst
+ sed -e 's/agetty -o/agetty -t 120 -o/' -i $file
+ done
+ return 0
+}
+
+## proxy_gateway_disable_rads
+proxy_gateway_disable_rads () {
+ # rads is really hard to kill
+ if [ ! -f /etc/rads.d/50_default.conf ] ; then
+ sed /etc/rads.d/30_default.conf > /etc/rads.d/50_default.conf \
+ -e 's@rads_start_display_manager=1@rads_start_display_manager=0@' \
+ -e 's@rads_skip_ram_test=0rads_skip_ram_test=1@' \
+ -e 's@rads_wait=0@rads_wait=1@' \
+ -e 's@rads_wait_seconds=10@rads_wait_seconds=20@' \
+ -e 's@rads_debug=0@rads_debug=1@'
+ fi
+ return 0
+}
+
+## proxy_gateway_install_tor
+proxy_gateway_install_tor () {
+ # fixme parameterize?
+
+ if [ ! -f /usr/local/etc/torrc.d/50_user.conf ] ; then
+ cat > /usr/local/etc/torrc.d/50_user.conf << EOF
+Socks5ProxyUsername foo
+Socks5ProxyPassword bar
+SafeLogging 0
+SocksPort 10.0.2.15:9050
+DnsPort 10.0.2.15:9053
+HTTPTunnelPort 10.0.2.15:9128
+TransPort 10.0.2.15:9040
+ControlSocket /run/tor/control
+ControlSocketGroupWriteable 1
+DisableNetwork 0
+EOF
+ fi
+
+ return 0
+}
+
+## proxy_gateway__shutup_verbosity
+proxy_gateway_shutup_verbosity () {
+ for file in /etc/issue* /etc/issue.d/* ; do
+ [ -f $file ] || continue
+ [ -s $file ] && cp /dev/null $file
+ done
+ return 0
+}
+
+## proxy_gateway_install_fstab
+proxy_gateway_install_fstab () {
+ # /etc/fstab
+
+ options=noauto,rw,trans=virtio,version=9p2000.L,cache=none
+ for elt in $SHARED_MNTS ; do
+ [ -d /mnt/$elt ] || mkdir /mnt/$elt
+ grep -q /mnt/$elt /etc/fstab && continue
+ echo "$elt /mnt/$elt 9p $options 0 0" \
+ >> /etc/fstab
+ done
+ return 0
+}
+
+## proxy_gateway_install_gagent
+proxy_gateway_install_gagent () {
+ [ -e /dev/virtio-ports/org.qemu.guest_agent.0 ] || {
+ ERROR /dev/virtio-ports/org.qemu.guest_agent.0 not found
+ ERROR "check the host xml for "
+ ERROR "or blame Pottyring's systemd"
+ }
+ [ -x /usr/sbin/qemu-ga ] && return 0
+
+ # /mnt/shared/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb
+ if [ -f /var/cache/apt/archives/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb ] ; then
+ # /o/Cache/Apt/Debian/10.6/deb.debian.org/debian-security/pool/updates/main/q/qemu/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb
+ dpkg -i /var/cache/apt/archives/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb
+ fi
+
+ false && \
+ [ -f /lib/systemd/system/qemu-guest-agent.service ] && \
+ [ ! -h /etc/systemd/system/multi-user.target/qemu-guest-agent.service ] && \
+ ln -s /lib/systemd/system/qemu-guest-agent.service \
+ /etc/systemd/system/multi-user.target.wants
+ return 0
+}
+
+## proxy_gateway_disable_services
+proxy_gateway_disable_services () {
+ [ -f /usr/local/etc/local.d/local.bash ] || \
+ { ERROR loading /usr/local/etc/local.d/local.bash ; return 2; }
+ local_systemd_stop_and_mask $DISABLE_SERVICES
+
+ return 0
+}
+
+## proxy_gateway_test
+proxy_gateway_test () {
+
+ proxy_whonix_test gateway
+
+ return 0
+}
+
+## proxy_gateway_config
+proxy_gateway_config () {
+ grep '^nameserver 127.0.0.1' /etc/resolv.conf || \
+ echo 'nameserver 127.0.0.1' >> /etc/resolv.conf
+ proxy_gateway_disable_services || return 1$?
+ # /usr/local/sbin/proxy_whonix_gateway_tor.bash config || return 2$?
+ gateway_tor_verify || return 3$?
+ return 0
+}
+
+## proxy_gateway_config
+proxy_gateway_config () {
+ local dire=gateway
+ local file
+
+ proxy_dest_port_wlan_config $dire || return 1$?
+ DEST=10.0.2.15
+ PORT=9053
+ [ -z "$PORT" -o -z "$DEST" ] && return 2
+ #? proxy_whonix_polipo_config $dire
+ proxy_ping_test_resolv $dire || return 4$?
+ proxy_whonix_dnsmasq_config $dire || return 5$?
+
+ return 0
+}
+## proxy_gateway_start_bg
+proxy_gateway_start_bg () { proxy_gateway_start $* ; }
+## proxy_gateway_start
+proxy_gateway_start () {
+ proxy_gateway_config || return 1$?
+ proxy_whonix_guest_start gateway
+
+ proxy_ping_dnsmasq_status || \
+ proxy_ping_dnsmasq_start || return 2$?
+
+ /usr/local/sbin/proxy_whonix_gateway_tor.bash start || return 3$?
+ #? . gateway_tor_start
+
+ #? polipo
+ # dnsmasq
+
+ return 0
+}
+
+## proxy_gateway_stop
+proxy_gateway_stop () {
+ gateway_tor_stop stop || return 3$?
+
+ return 0
+}
+
+## proxy_gateway_status
+proxy_gateway_status () {
+
+ if [ -f /etc/ssh/sshd_config ] ; then
+ rc_service sshd status
+ else
+ WARN ssh not installed
+ fi
+
+ # tor_grep_log || return 2$?
+ tor_status
+
+ #? /usr/local/bin/proxy_ping_test.bash polipo || return 3$?
+ /usr/local/bin/proxy_ping_test.bash gateway || return 3$?
+ /usr/local/bin/proxy_ping_test.bash dns || return 4$?
+
+ return 0
+}
+
+## proxy_gateway_config
+proxy_gateway_config () {
+ systemctl is-enabled rc.local || systemctl enable --now rc.local || return 1
+# [ -f /etc/systemd/system/multi-user.target.wants/rc-local.service ] || \
+# ln -s /lib/systemd/system/rc-local.service \
+# /etc/systemd/system/multi-user.target.wants/rc-local.service
+
+ systemctl is-enabled tor || systemctl disable --now tor
+ tor_config_tor || return 1$?
+
+ return 0
+}
+
+proxy_gateway_verify () {
+ for elt in $( echo $USAGE | sed -e 's/|/ /' ) do ; grep ^$elt $0 ; done
+ tor_do_verify || return 1
+
+ return 0
+}
+
+## proxy_gateway_install
+proxy_gateway_install () {
+ proxy_gateway_config || return 0
+
+ proxy_gateway_install_gagent
+ proxy_gateway_fix_getty_timeout
+ proxy_gateway_install_tor
+ proxy_gateway_shutup_verbosity
+ proxy_gateway_install_fstab
+ proxy_gateway_disable_rads
+
+ return 0
+}
+
+if [ "$#" -eq 0 ] ; then
+ echo USAGE: $prog $USAGE
+ elif [ "$1" = '-h' ] || [ "$1" = '--help' ] ; then
+ echo USAGE: $prog $USAGE or:
+ grep '^## ' $0 | sed -e 's/^## //'
+
+ elif [ "$1" = config -o "$1" -o "$1" = install ] ; then
+ proxy_gateway_$1 || return 3$?
+
+ elif [ "$1" = verify -o "$1" = status -o "$1" = test_from -o "$1" = test ] ; then
+ proxy_gateway_$1 || return 4$?
+
+ elif [ "$1" = start_bg -o "$1" = start -o "$1" = stop ] ; then
+ proxy_gateway_$1 || return 5$?
+
+ else
+ INFO $prog "$@"
+ eval "$@"
+ exit $?
+
+ fi
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_guest_vda.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_vda.bash
new file mode 100755
index 0000000..4220846
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_vda.bash
@@ -0,0 +1,161 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=proxy
+MODE=vda
+CONN=guest
+USAGE="[config|start|stop|status|restart|verify|test]"
+
+[ $( id -u ) -eq 0 ] || { ERROR you must be root ; exit 1 ; }
+prog=$( basename $0 .bash )
+
+export PATH=$PATH:/usr/local/sbin
+. /usr/local/bin/usr_local_tput.bash || exit 2
+PREFIX=/usr/local
+
+NEEDED_SCRIPTS="
+/usr/local/bin/proxy_ping_test.bash
+/usr/local/sbin/proxy_whonix_gateway_tor.bash
+"
+. /usr/local/etc/local.d/local.bash || exit 1
+. /usr/local/sbin/proxy_whonix_lib.bash || \
+ { ERROR loading /usr/local/sbin/proxy_whonix_lib.bash ; exit 2; }
+
+# vda does not need dnsmasq
+# $DEST resolv.conf
+
+## proxy_vda_stop
+proxy_vda_stop () {
+
+ return 0
+}
+
+## tor_init_check_iptables
+proxy_vda_init_check_iptables () {
+ # tor_init_check_iptables || return 1$?
+ return 0
+}
+
+## proxy_vda_config
+proxy_vda_config () {
+ proxy_whonix_guest_config || return 1$?
+
+ [ -f /etc/firewall.conf.vda ] && \
+ cp -p /usr/local/etc/firewall.conf.vda /etc/firewall.conf.vda
+
+ proxy_guest_firewall_config || return 2$?
+ #/usr/local/sbin/proxy_whonix_guest_workstation-firewall.bash > \
+ # /etc/firewall.conf.ws.new
+
+ proxy_vda_whonix_config
+
+ return 0
+}
+
+## proxy_vda_verify
+proxy_vda_verify () {
+
+ for elt in $(echo $USAGE | sed -e 's/|/ /') ; do grep ^$elt $0 ; done
+
+ return 0
+}
+
+proxy_vda_grep_logs () {
+
+ return 0
+}
+
+## proxy_vda_test
+proxy_vda_test () {
+
+ proxy_whonix_test vda || return 3$?
+
+ return 0
+}
+
+## proxy_vda_status
+proxy_vda_status () {
+ netstat -nle4 | grep -q 127.0.0.1:3128 >/dev/null || \
+ { [ -n "$DEBUG" ] && WARN $0 polipo not running ; return 1 ; }
+ [ -n "$DEBUG" ] && DBUG $0 polipo running
+
+ /usr/local/bin/proxy_ping_test.bash vda
+ /usr/local/bin/proxy_ping_test.bash polipo
+ /usr/local/bin/proxy_ping_test.bash dns
+
+ return 0
+}
+
+## proxy_vda_whonix_start
+proxy_vda_whonix_start () {
+ local dire=vda
+ local ret
+
+ #? proxy_whonix_guest_start
+
+ proxy_whonix_polipo_start $dire || \
+ { ret=$? ;ERROR $prog polipo not running ret=$ret ; return 4$ret ; }
+
+ return 0
+}
+
+## proxy_vda_start
+proxy_vda_start () {
+ # local_guest_start_services
+ local PROXY_WLAN_GW=10.152.152.10
+ local IP=10.152.152.11
+
+ grep -q gateway /etc//hosts || grep $PROXY_WLAN_GW gateway >> /etc//hosts
+
+ if ! ifconfig eth0 | grep -q $IP ; then
+ ifconfig eth0 $IP netmask 255.255.192.0 broadcast 10.152.191.255
+ #? inet $IP netmask 255.0.0.0 broadcast 10.255.255.255
+ fi
+ ip route | grep -q ^default || \
+ route add default gw $PROXY_WLAN_GW
+
+ # dnsmasq
+ echo nameserver $PROXY_WLAN_GW > /etc/resolv.conf
+
+ [ -f /etc/firewall.conf.vda ] || exit 2
+ if [ -f /etc/firewall.conf.vda -a ! -f /etc/firewall.conf ] ; then
+ cp -p /etc/firewall.conf.vda /etc/firewall.conf
+ proxy_iptables_restore < /etc/firewall.conf
+ elif ! diff -q /etc/firewall.conf.vda /etc/firewall.conf ; then
+ mv /etc/firewall.conf /etc/firewall.conf.bak
+ cp -p /etc/firewall.conf.vda /etc/firewall.conf
+ proxy_iptables -F; proxy_iptables_restore < /etc/firewall.conf
+ fi
+ proxy_iptables_save | grep -i reject || return 3
+
+ proxy_vda_whonix_start
+
+ return 0
+}
+
+if [ "$#" -eq 0 ] ; then
+ echo USAGE: $prog $USAGE
+
+ elif [ "$1" = '-h' ] || [ "$1" = '--help' ] ; then
+ echo USAGE: $prog $USAGE or:
+ grep '^## ' $0 | sed -e 's/^## //'
+
+ elif [ "$1" = config -o "$1" = 'install' ] ; then
+ proxy_vda_config || exit 3$?
+
+ elif [ "$1" = verify -o "$1" = 'test' ] ; then
+ proxy_vda_$1 || exit 4$?
+
+ elif [ "$1" = update -o "$1" = 'start' -o "$1" = 'status' -o "$1" = 'stop' ] ; then
+ proxy_vda_$1 || exit 5$?
+
+ elif [ "$1" = hourly -o "$1" = 'refresh' ] ; then
+ proxy_vda_refresh || exit 6$?
+
+ else
+ eval "$@"
+ exit $?
+
+ fi
+
+exit 0
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_guest_workstation-firewall.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_workstation-firewall.bash
new file mode 100755
index 0000000..b707e20
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_workstation-firewall.bash
@@ -0,0 +1,624 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+prog=$( basename $0 .bash )
+ROLE=proxy
+MODE=all
+iptables_cmd='echo iptables'
+ip6tables_cmd='echo iptables >/dev/null'
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+#### meta start
+#### project Whonix
+#### category networking and firewall
+#### description
+## firewall script
+#### meta end
+
+## NOTE: If you make changes to this firewall, think about, if it would
+## make sense to add the changes to Whonix-Gateway script as well.
+## Some things like dropping invalid packages, should be shared.
+
+## TODO:
+## - Should allow unlimited TCP/UDP/IPv6 traffic on the virtual external interface (OnionCat / OpenVPN).
+
+## source for some rules:
+## http://www.cyberciti.biz/faq/ip6tables-ipv6-firewall-for-linux/
+
+set -e
+
+error_handler() {
+ echo "$0 ##################################################"
+ echo "$0 ERROR: Whonix firewall script failed!"
+ echo "$0 ##################################################"
+
+ exit 1
+}
+
+# trap "error_handler" ERR
+
+init() {
+ output_cmd "OK: Loading Whonix firewall..."
+
+ set -o pipefail
+ set -o errtrace
+}
+
+source_config_folder() {
+ shopt -s nullglob
+ local i
+ for i in \
+ /etc/whonix_firewall.d/*.conf \
+ /usr/local/etc/whonix_firewall.d/*.conf \
+ ; do
+ bash_n_exit_code="0"
+ bash_n_output="$(bash -n "$i" 2>&1)" || { bash_n_exit_code="$?" ; true; };
+ if [ ! "$bash_n_exit_code" = "0" ]; then
+ output_cmd "ERROR: Invalid config file: $i
+ bash_n_exit_code: $bash_n_exit_code
+ bash_n_output:
+ $bash_n_output" >&2
+ exit 1
+ fi
+ source "$i"
+ done
+}
+
+variables_defaults() {
+ [ -n "$iptables_cmd" ] || iptables_cmd="iptables --wait"
+ [ -n "$ip6tables_cmd" ] || ip6tables_cmd="ip6tables --wait"
+
+ ## Legacy.
+ if [ "$VPN_FIREWALL" = "1" ]; then
+ TUNNEL_FIREWALL_ENABLE="true"
+ fi
+
+ ## Not in use/defined yet.
+ ## INT_IF could be the internal network.
+ ## EXT_IF could be an additional virtual network adapter,
+ ## such as OnionCat or OpenVPN.
+
+ ## External interface
+ [ -n "$EXT_IF" ] || EXT_IF="eth0"
+ ## Internal interface
+ [ -n "$INT_IF" ] || INT_IF="eth1"
+
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ ## Would fail if netvm is set to 'none',
+ ## which is the case in Qubes R4 TemplateVMs.
+ [ -n "$GATEWAY_IP" ] || GATEWAY_IP="$(qubesdb-read /qubes-gateway 2>/dev/null)" || GATEWAY_IP="127.0.0.1"
+ else
+ [ -n "$GATEWAY_IP" ] || GATEWAY_IP="10.152.152.10"
+ fi
+
+ ## Since hardcoded in anon-ws-disable-stacked-tor.
+ [ -n "$GATEWAY_IP_HARDCODED" ] || GATEWAY_IP_HARDCODED="10.152.152.10"
+
+ [ -n "$TUNNEL_USER" ] || TUNNEL_USER="$(id -u tunnel 2>/dev/null)" || true
+ [ -n "$NOTUNNEL_USER" ] || NOTUNNEL_USER="$(id -u notunnel 2>/dev/null)" || true
+ [ -n "$UPDATESPROXYCHECK_USER" ] || UPDATESPROXYCHECK_USER="$(id -u updatesproxycheck 2>/dev/null)" || true
+
+ [ -n "$SDWDATE_USER" ] || SDWDATE_USER="$(id -u sdwdate 2>/dev/null)" || true
+ [ -n "$WHONIXCHECK_USER" ] || WHONIXCHECK_USER="$(id -u whonixcheck 2>/dev/null)" || true
+
+ [ -n "$TUNNEL_FIREWALL_ALLOW_NOTUNNEL_USER" ] || TUNNEL_FIREWALL_ALLOW_NOTUNNEL_USER="true"
+
+ ## Control Port Filter Proxy Port
+ [ -n "$CONTROL_PORT_FILTER_PROXY_PORT" ] || CONTROL_PORT_FILTER_PROXY_PORT="9051"
+
+ [ -n "$qubes_updates_proxy_port" ] || qubes_updates_proxy_port="8082"
+
+ ## Socks Ports for per application circuits.
+ [ -n "$SOCKS_PORT_TOR_DEFAULT" ] || SOCKS_PORT_TOR_DEFAULT="9050"
+ [ -n "$SOCKS_PORT_TB" ] || SOCKS_PORT_TB="9100"
+ [ -n "$SOCKS_PORT_IRC" ] || SOCKS_PORT_IRC="9101"
+ [ -n "$SOCKS_PORT_TORBIRDY" ] || SOCKS_PORT_TORBIRDY="9102"
+ [ -n "$SOCKS_PORT_IM" ] || SOCKS_PORT_IM="9103"
+ [ -n "$SOCKS_PORT_APT_GET" ] || SOCKS_PORT_APT_GET="9104"
+ [ -n "$SOCKS_PORT_GPG" ] || SOCKS_PORT_GPG="9105"
+ [ -n "$SOCKS_PORT_SSH" ] || SOCKS_PORT_SSH="9106"
+ [ -n "$SOCKS_PORT_GIT" ] || SOCKS_PORT_GIT="9107"
+ [ -n "$SOCKS_PORT_SDWDATE" ] || SOCKS_PORT_SDWDATE="9108"
+ [ -n "$SOCKS_PORT_WGET" ] || SOCKS_PORT_WGET="9109"
+ [ -n "$SOCKS_PORT_WHONIXCHECK" ] || SOCKS_PORT_WHONIXCHECK="9110"
+ [ -n "$SOCKS_PORT_BITCOIN" ] || SOCKS_PORT_BITCOIN="9111"
+ [ -n "$SOCKS_PORT_PRIVOXY" ] || SOCKS_PORT_PRIVOXY="9112"
+ [ -n "$SOCKS_PORT_POLIPO" ] || SOCKS_PORT_POLIPO="9113"
+ [ -n "$SOCKS_PORT_WHONIX_NEWS" ] || SOCKS_PORT_WHONIX_NEWS="9114"
+ [ -n "$SOCKS_PORT_TBB_DOWNLOAD" ] || SOCKS_PORT_TBB_DOWNLOAD="9115"
+ [ -n "$SOCKS_PORT_TBB_GPG" ] || SOCKS_PORT_TBB_GPG="9116"
+ [ -n "$SOCKS_PORT_CURL" ] || SOCKS_PORT_CURL="9117"
+ [ -n "$SOCKS_PORT_RSS" ] || SOCKS_PORT_RSS="9118"
+ [ -n "$SOCKS_PORT_TORCHAT" ] || SOCKS_PORT_TORCHAT="9119"
+ [ -n "$SOCKS_PORT_MIXMASTERUPDATE" ] || SOCKS_PORT_MIXMASTERUPDATE="9120"
+ [ -n "$SOCKS_PORT_MIXMASTER" ] || SOCKS_PORT_MIXMASTER="9121"
+ [ -n "$SOCKS_PORT_KDE" ] || SOCKS_PORT_KDE="9122"
+ [ -n "$SOCKS_PORT_GNOME" ] || SOCKS_PORT_GNOME="9123"
+ [ -n "$SOCKS_PORT_APTITUDE" ] || SOCKS_PORT_APTITUDE="9124"
+ [ -n "$SOCKS_PORT_YUM" ] || SOCKS_PORT_YUM="9125"
+ [ -n "$SOCKS_PORT_TBB_DEFAULT" ] || SOCKS_PORT_TBB_DEFAULT="9150"
+
+ socks_ports_list="$(compgen -v | grep SOCKS\_PORT\_)"
+
+ [ -n "$VPN_INTERFACE" ] || VPN_INTERFACE="tun0"
+
+ ## Destinations you do not routed through VPN.
+ if [ "$LOCAL_NET" = "" ]; then
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ LOCAL_NET="\
+ 127.0.0.0-127.0.0.24 \
+ 10.137.0.0-10.138.255.255 \
+ "
+ else
+ ## 10.0.2.2/24: VirtualBox DHCP
+ LOCAL_NET="\
+ 127.0.0.0-127.0.0.24 \
+ 192.168.0.0-192.168.0.24 \
+ 192.168.1.0-192.168.1.24 \
+ 10.152.152.0-10.152.152.24 \
+ 10.0.2.2-10.0.2.24 \
+ "
+ fi
+ fi
+}
+
+ipv4_defaults() {
+ ## Set secure defaults.
+ $iptables_cmd -P INPUT DROP
+
+ ## FORWARD rules does not actually do anything if forwarding is disabled. Better be safe just in case.
+ $iptables_cmd -P FORWARD DROP
+
+ ## Will be lifted below.
+ $iptables_cmd -P OUTPUT DROP
+}
+
+ipv4_preparation() {
+ ## Flush old rules.
+ $iptables_cmd -F
+ $iptables_cmd -X
+ $iptables_cmd -t nat -F
+ $iptables_cmd -t nat -X
+ $iptables_cmd -t mangle -F
+ $iptables_cmd -t mangle -X
+}
+
+ipv4_drop_invalid_incoming_packages() {
+ ## DROP MARTIANS
+## https://www.cyberciti.biz/faq/linux-log-suspicious-martian-packets-un-routable-source-addresses/
+ $iptables_cmd -A INPUT -i wlan6 -s 10.0.0.0/8 -j LOG --log-prefix "iptables_martian_DROP SPOOF A: "
+ $iptables_cmd -A INPUT -i wlan6 -s 172.16.0.0/12 -j LOG --log-prefix "iptables_martian_DROP SPOOF B: "
+ $iptables_cmd -A INPUT -i wlan6 -s 192.168.0.0/16 -j LOG --log-prefix "iptables_martian_DROP SPOOF C: "
+ $iptables_cmd -A INPUT -i wlan6 -s 224.0.0.0/4 -j LOG --log-prefix "iptables_martian_DROP MULTICAST D: "
+ $iptables_cmd -A INPUT -i wlan6 -s 240.0.0.0/5 -j LOG --log-prefix "iptables_martian_DROP SPOOF E: "
+ $iptables_cmd -A INPUT -i wlan6 -d 127.0.0.0/8 -j LOG --log-prefix "iptables_martian_DROP LOOPBACK: "
+
+ $iptables_cmd -A INPUT -i wlan6 -s 10.0.0.0/8 -j DROP
+ $iptables_cmd -A INPUT -i wlan6 -s 172.16.0.0/12 -j DROP
+ $iptables_cmd -A INPUT -i wlan6 -s 192.168.0.0/16 -j DROP
+ $iptables_cmd -A INPUT -i wlan6 -s 224.0.0.0/4 -j DROP
+ $iptables_cmd -A INPUT -i wlan6 -s 240.0.0.0/5 -j DROP
+ $iptables_cmd -A INPUT -i wlan6 -d 127.0.0.0/8 -j DROP
+
+ ## DROP INVALID
+ $iptables_cmd -A INPUT -m conntrack --ctstate INVALID -j DROP
+ $iptables_cmd -A INPUT -m state --state INVALID -j DROP
+
+ ## DROP INVALID SYN PACKETS
+ $iptables_cmd -A INPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
+ $iptables_cmd -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
+ $iptables_cmd -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
+
+ ## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
+ $iptables_cmd -A INPUT -f -j DROP
+
+ ## DROP INCOMING MALFORMED XMAS PACKETS
+ $iptables_cmd -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
+
+ ## DROP INCOMING MALFORMED NULL PACKETS
+ $iptables_cmd -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
+}
+
+qubes() {
+ ## Not yet required. Just so Whonix-Workstation firewall can be more similar
+ ## to Whonix-Gateway firewall.
+ true
+}
+
+qubes_dns() {
+ local counter
+ counter=0
+
+ ## Using '2>/dev/null' because 'qubesdb-read' DNS would fail in Qubes R4
+ ## TemplateVMs, because these are non-networked by default.
+
+ if qubes_primary_dns="$(qubesdb-read /qubes-primary-dns 2>/dev/null)" ; then
+ $iptables_cmd -A OUTPUT -p udp --dport 53 --dst "$qubes_primary_dns" -j ACCEPT
+ counter=$(( counter + 1 ))
+ fi
+
+ if qubes_secondary_dns="$(qubesdb-read /qubes-secondary-dns 2>/dev/null)" ; then
+ $iptables_cmd -A OUTPUT -p udp --dport 53 --dst "$qubes_secondary_dns" -j ACCEPT
+ counter=$(( counter + 1 ))
+ fi
+
+ if [ "$counter" -ge "2" ]; then
+ output_cmd "OK: Qubes DNS firewall rules ok."
+ else
+ $iptables_cmd -A OUTPUT -p udp --dport 53 -j ACCEPT
+ fi
+}
+
+ipv4_input_rules() {
+ ## Traffic on the loopback interface is accepted.
+ $iptables_cmd -A INPUT -i lo -j ACCEPT
+
+ ## Established incoming connections are accepted.
+ $iptables_cmd -A INPUT -m state --state ESTABLISHED -j ACCEPT
+
+ ## Allow all incoming connections on the virtual VPN network interface,
+ ## when TUNNEL_FIREWALL_ENABLE mode is enabled.
+ ## DISABLED BY DEFAULT.
+ if [ "$TUNNEL_FIREWALL_ENABLE" = "true" ]; then
+ $iptables_cmd -A INPUT -i "$VPN_INTERFACE" -j ACCEPT
+ fi
+
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true "firewall_mode is $firewall_mode, therefore not opening EXTERNAL_OPEN_PORTS."
+ else
+ local local_port_to_open
+ for local_port_to_open in $EXTERNAL_OPEN_PORTS; do
+ $iptables_cmd -A INPUT -p tcp --dport "$local_port_to_open" -j ACCEPT
+ done
+
+ local local_udp_port_to_open
+ for local_udp_port_to_open in $EXTERNAL_UDP_OPEN_PORTS; do
+ $iptables_cmd -A INPUT -p udp --dport "$local_udp_port_to_open" -j ACCEPT
+ done
+
+ if [ "$EXTERNAL_OPEN_ALL" = "true" ]; then
+ $iptables_cmd -A INPUT -j ACCEPT
+ fi
+ fi
+}
+
+ipv4_input_defaults() {
+ ## Log.
+ #$iptables_cmd -A INPUT -j LOG --log-prefix "Whonix blocked input4: "
+
+ ## Required for Control Port Filter Proxy Connection.
+ ## https://phabricator.whonix.org/T112
+ $iptables_cmd -A INPUT -p tcp -j REJECT --reject-with tcp-reset
+
+ ## Reject anything not explicitly allowed above.
+ $iptables_cmd -A INPUT -j REJECT --reject-with icmp-port-unreachable
+}
+
+ipv4_forward() {
+ ## Log.
+ #$iptables_cmd -A FORWARD -j LOG --log-prefix "Whonix blocked forward4: "
+
+ $iptables_cmd -A FORWARD -j DROP
+}
+
+ipv4_reject_invalid_outgoing_packages() {
+ ## Drop invalid outgoing packages,
+ ## unless NO_REJECT_INVALID_OUTGOING_PACKAGES is set to 1.
+ if [ ! "$NO_REJECT_INVALID_OUTGOING_PACKAGES" = "1" ]; then
+ ## https://lists.torproject.org/pipermail/tor-talk/2014-March/032507.html
+ $iptables_cmd -A OUTPUT -m conntrack --ctstate INVALID -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -m state --state INVALID -j REJECT --reject-with icmp-admin-prohibited
+ #$iptables_cmd -A OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,FIN ACK,FIN -j REJECT --reject-with icmp-admin-prohibited
+ #$iptables_cmd -A OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,RST ACK,RST -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP INVALID SYN PACKETS
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags SYN,RST SYN,RST -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
+ $iptables_cmd -A OUTPUT -f -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP INCOMING MALFORMED XMAS PACKETS
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags ALL ALL -j REJECT --reject-with icmp-admin-prohibited
+
+ ## DROP INCOMING MALFORMED NULL PACKETS
+ $iptables_cmd -A OUTPUT -p tcp --tcp-flags ALL NONE -j REJECT --reject-with icmp-admin-prohibited
+ fi
+}
+
+qubes_updates_proxy() {
+ ## Detect Qubes.
+ if ! command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ return 0
+ fi
+
+ ## Detect being run inside TemplateVM.
+ if [ ! -f "/run/qubes/this-is-templatevm" ]; then
+ return 0
+ fi
+
+ ## Detect if torified Qubes updates proxy was detected.
+ if test -f "/run/qubes-service/whonix-secure-proxy" ; then
+ output_cmd "OK: Torified Qubes Updates Proxy check ok. Full access to Qubes Updates Proxy."
+ return 0
+ fi
+
+ output_cmd "OK: Torified Qubes Updates Proxy check not done yet. Limiting access to Qubes Updates Proxy to user 'updatesproxycheck'."
+
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$UPDATESPROXYCHECK_USER" -m iprange --dst-range "127.0.0.1" -p tcp --dport "$qubes_updates_proxy_port" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$UPDATESPROXYCHECK_USER" -m iprange --dst-range "10.137.255.254" -p tcp --dport "$qubes_updates_proxy_port" -j ACCEPT
+
+ $iptables_cmd -A OUTPUT -m iprange --dst-range "127.0.0.1" -p tcp --dport "$qubes_updates_proxy_port" -j REJECT --reject-with icmp-admin-prohibited
+ $iptables_cmd -A OUTPUT -m iprange --dst-range "10.137.255.254" -p tcp --dport "$qubes_updates_proxy_port" -j REJECT --reject-with icmp-admin-prohibited
+}
+
+ipv4_output() {
+ ## Prevent connections to Tor SocksPorts.
+ ## https://phabricator.whonix.org/T533#11025
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ local socks_port_item
+ for socks_port_item in $socks_ports_list; do
+ true "$socks_port_item: ${!socks_port_item}"
+ if [ "$SOCKS_PORT_SDWDATE" = "${!socks_port_item}" ]; then
+ continue
+ fi
+ $iptables_cmd -A OUTPUT -p tcp --dport "${!socks_port_item}" --dst "127.0.0.1" -j REJECT
+ done
+ fi
+
+ qubes_updates_proxy
+
+ ## Access to localhost is required even in timesync-fail-closed mode,
+ ## otherwise breaks applications such as konsole and kwrite.
+ $iptables_cmd -A OUTPUT -o lo -j ACCEPT
+
+ ## Allow outgoing traffic on VPN interface,
+ ## if TUNNEL_FIREWALL_ENABLE mode is enabled.
+ ## DISABLED BY DEFAULT.
+ if [ "$TUNNEL_FIREWALL_ENABLE" = "true" ]; then
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true "firewall_mode is $firewall_mode, therefore prohibiting user $TUNNEL_USER traffic."
+ else
+ true "firewall_mode is $firewall_mode, therefore allowing user $TUNNEL_USER traffic."
+ ## Connections to VPN servers are allowed,
+ $iptables_cmd -A OUTPUT -o "$VPN_INTERFACE" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$TUNNEL_USER" -j ACCEPT
+ fi
+
+ if [ "$TUNNEL_FIREWALL_ALLOW_SDWDATE_USER" = "true" ]; then
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ fi
+
+ if [ "$TUNNEL_FIREWALL_ALLOW_NOTUNNEL_USER" = "true" ]; then
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$NOTUNNEL_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$NOTUNNEL_USER" -m iprange --dst-range "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$NOTUNNEL_USER" -m iprange --dst-range "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ fi
+
+ ## Accept outgoing connections to local network.
+ if [ "$TUNNEL_FIREWALL_ALLOW_LOCAL_NET" = "true" ]; then
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true
+ else
+ local local_net_item
+ for local_net_item in $LOCAL_NET; do
+ $iptables_cmd -A OUTPUT -m iprange --dst-range "$local_net_item" -j ACCEPT
+ done
+ fi
+ fi
+
+ if [ "$TUNNEL_FIREWALL_ALLOW_CONTROL_PORT_FILTER_PROXY" = "true" ]; then
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ fi
+
+ if [ "$TUNNEL_FIREWALL_ALLOW_TB_UPDATER" = "true" ]; then
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true
+ else
+ local socks_port_tbb
+ for socks_port_tbb in $SOCKS_PORT_TBB_DOWNLOAD $SOCKS_PORT_TBB_GPG ; do
+ $iptables_cmd -A OUTPUT -p tcp --dport "$socks_port_tbb" --dst "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p tcp --dport "$socks_port_tbb" --dst "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ done
+ fi
+ fi
+
+ if [ "$TUNNEL_FIREWALL_ALLOW_WHONIXCHECK" = "true" ]; then
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true
+ else
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ fi
+ fi
+ else
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true "firewall_mode is $firewall_mode, therefore prohibiting DNS traffic."
+ else
+ true "firewall_mode is $firewall_mode, therefore allowing DNS traffic."
+ ## Allow Whonix-Workstation to query Whonix-Gateway for DNS.
+ $iptables_cmd -A OUTPUT -p udp --dport 53 --dst "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p udp --dport 53 --dst "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ if command -v "qubesdb-read" >/dev/null 2>&1 ; then
+ qubes_dns
+ fi
+ fi
+
+ ## Not sure about the next one. UDP is not supported by Tor, why not
+ ## block any outgoing UDP. Might have unwanted side effects when tunneling
+ ## UDP over Tor.
+ ## https://www.whonix.org/wiki/Tunnel_UDP_over_Tor
+ ##
+ ## All other non-TCP protocol traffic gets rejected.
+ ## iptables knows 7 different protocols and all.
+ ## (tcp, udp, udplite, icmp, esp, ah, sctp or all)
+ ##
+ ## (1) ping torproject.org
+ ## 4 packets transmitted, 0 received, 100% packet loss, time 3000ms
+ ##
+ ## (2) ping torproject.org
+ ## From 10.152.152.11 icmp_seq=1 Destination Port Unreachable
+ ## 0 packets transmitted, 0 received, +100 errors
+ ##
+ ## The next rule ensures, that only tcp can leave and achieves the desired result from (2).
+ $iptables_cmd -A OUTPUT ! -p tcp -j REJECT --reject-with icmp-port-unreachable
+
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ true "firewall_mode is $firewall_mode, therefore prohibiting all outgoing traffic."
+
+ ## Allow sdwdate talking to localhost and Tor in Whonix firewall timesync-fail-closed mode.
+ ## Otherwise in Whonix firewall full mode this rule is redundant.
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$SDWDATE_USER" -m iprange --dst-range "$GATEWAY_IP_HARDCODED" -j ACCEPT
+
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -m owner --uid-owner "$WHONIXCHECK_USER" -m iprange --dst-range "$GATEWAY_IP_HARDCODED" -j ACCEPT
+
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "127.0.0.1" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "$GATEWAY_IP" -j ACCEPT
+ $iptables_cmd -A OUTPUT -p tcp --dport "$CONTROL_PORT_FILTER_PROXY_PORT" --dst "$GATEWAY_IP_HARDCODED" -j ACCEPT
+ else
+ true "firewall_mode is $firewall_mode, therefore allowing all outgoing traffic."
+ ## Allow full outgoing connection but no incoming stuff.
+ $iptables_cmd -A OUTPUT -j ACCEPT
+ fi
+
+ ## Log.
+ #$iptables_cmd -A OUTPUT -j LOG --log-prefix "Whonix blocked output4: "
+
+ ## Reject all other outgoing traffic.
+ $iptables_cmd -A OUTPUT -j REJECT --reject-with icmp-port-unreachable
+ fi
+}
+
+ipv6() {
+ ## Policy DROP for all traffic as fallback.
+ $ip6tables_cmd -P INPUT DROP
+ $ip6tables_cmd -P OUTPUT DROP
+ $ip6tables_cmd -P FORWARD DROP
+
+ ## Flush old rules.
+ $ip6tables_cmd -F
+ $ip6tables_cmd -X
+ $ip6tables_cmd -t mangle -F
+ $ip6tables_cmd -t mangle -X
+
+ ## Allow unlimited access on loopback.
+ $ip6tables_cmd -A INPUT -i lo -j ACCEPT
+ $ip6tables_cmd -A OUTPUT -o lo -j ACCEPT
+
+ ## Log.
+ #$ip6tables_cmd -A INPUT -j LOG --log-prefix "Whonix blocked input6: "
+ #$ip6tables_cmd -A OUTPUT -j LOG --log-prefix "Whonix blocked output6: "
+ #$ip6tables_cmd -A FORWARD -j LOG --log-prefix "Whonix blocked forward6: "
+
+ ## Drop/reject all other traffic.
+ $ip6tables_cmd -A INPUT -j DROP
+ ## --reject-with icmp-admin-prohibited not supported by ip6tables
+ $ip6tables_cmd -A OUTPUT -j REJECT --reject-with icmp6-port-unreachable
+ ## --reject-with icmp-admin-prohibited not supported by ip6tables
+ $ip6tables_cmd -A FORWARD -j DROP
+}
+
+status_files() {
+ mkdir --parents /run/whonix_firewall
+ if [ -e /run/whonix_firewall/first_run_current_boot.status ]; then
+ touch /run/whonix_firewall/consecutive_run.status
+ return 0
+ fi
+ touch /run/whonix_firewall/first_run_current_boot.status
+}
+
+date_cmd(){
+ date -u +"%Y-%m-%d %T"
+}
+
+output_cmd() {
+ echo "$(date_cmd) - $0 - $@"
+}
+
+firewall_mode_detection() {
+ if [ ! "$firewall_mode" = "" ]; then
+ output_cmd "OK: Skipping firewall mode detection since already set to '$firewall_mode'."
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ output_cmd "OK: (Only local Tor control port connections and torified sdwdate allowed.)"
+ return 0
+ elif [ "$firewall_mode" = "full" ]; then
+ output_cmd "OK: (Full torified network access allowed.)"
+ return 0
+ else
+ output_cmd "ERROR: firewall_mode must be set to either 'full' or 'timesync-fail-closed'."
+ error_handler
+ fi
+ fi
+
+ ## Run Whonix firewall in full mode if sdwdate already succeeded.
+ if [ -e /run/sdwdate/first_success ]; then
+ firewall_mode=full
+ output_cmd "OK: (/run/sdwdate/first_success exists.)"
+ elif [ -e /run/sdwdate/success ]; then
+ firewall_mode=full
+ output_cmd "OK: (/run/sdwdate/success exists.)"
+ ## /run/whonix_firewall/first_run_current_boot.status already exists,
+ ## therefore have Whonix firewall run in full mode.
+ elif [ -e /run/whonix_firewall/first_run_current_boot.status ]; then
+ firewall_mode=full
+ output_cmd "OK: (/run/whonix_firewall/first_run_current_boot.status exists.)"
+ else
+ ## /run/whonix_firewall/first_run_current_boot.status does not yet exist,
+ ## therefore return 'yes, timesync-fail-closed'.
+ firewall_mode=timesync-fail-closed
+ fi
+
+ if [ "$firewall_mode" = "timesync-fail-closed" ]; then
+ output_cmd "OK: First run during current boot, therefore running in timesync-fail-closed mode."
+ output_cmd "OK: (Only local Tor control port connections and torified sdwdate allowed.)"
+ else
+ output_cmd "OK: Consecutive run during current boot, therefore running in full mode."
+ output_cmd "OK: (Full torified network access allowed.)"
+ fi
+}
+
+end() {
+ output_cmd "OK: Whonix firewall loaded."
+
+ exit 0
+}
+
+main() {
+ init
+ firewall_mode_detection
+ variables_defaults
+ ipv4_defaults
+ ipv4_preparation
+ ipv4_drop_invalid_incoming_packages
+ qubes
+ ipv4_input_rules
+ ipv4_input_defaults
+ ipv4_forward
+ ipv4_reject_invalid_outgoing_packages
+ ipv4_output
+ if [ -d /proc/sys/net/ipv6/ ]; then
+ ipv6
+ fi
+ status_files
+ end
+}
+
+if [ -x /usr/bin/basename ] && [ $( basename -- $0 ) = 'proxy_whonix_guest_workstation-firewall.bash' ] ; then
+ source_config_folder
+ iptables_cmd="echo iptables"
+ ip6tables_cmd="echo # ip6tables"
+ main
+
+ fi
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_guest_workstation.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_workstation.bash
new file mode 100755
index 0000000..51aa44c
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_guest_workstation.bash
@@ -0,0 +1,195 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=proxy
+[ -n "$prog" ] || prog= # no qa
+prog=$( basename $0 .bash )
+. /usr/local/bin/usr_local_tput.bash
+
+USAGE="[config|start|stop|status|restart|test]"
+
+SHARED_MNTS="o"
+
+[ "$#" -eq 0 ] && set -- install
+
+## proxy_workstation_fix_getty_timeout
+proxy_workstation_fix_getty_timeout () {
+ # fix_getty_timeout - wheres inittab
+ grep -l '^Exec.*agetty -o' /lib/systemd/system/*service | while read file ; do
+ [ -f $file.dst ] && continue
+ cp -p $file $file.dst
+ sed -e 's/agetty -o/agetty -t 120 -o/' -i $file
+ done
+ return 0
+}
+
+
+## proxy_workstation__shutup_verbosity
+proxy_workstation_shutup_verbosity () {
+ for file in /etc/issue* /etc/issue.d/* ; do
+ [ -f $file ] || continue
+ [ -s $file ] && cp /dev/null $file
+ done
+ return 0
+}
+
+## proxy_workstation_install_fstab
+proxy_workstation_install_fstab () {
+ # /etc/fstab
+ options=noauto,rw,trans=virtio,version=9p2000.L,cache=none
+ for elt in $SHARED_MNTS ; do
+ [ -d /mnt/$elt ] || mkdir /mnt/$elt
+ grep -q /mnt/$elt /etc/fstab && continue
+ echo "$elt /mnt/$elt 9p $options 0 0" \
+ >> /etc/fstab
+ done
+ # root
+ return 0
+}
+
+## proxy_workstation_install_gagent
+proxy_workstation_install_gagent () {
+ [ -d /etc/apt ] && proxy_workstation_install_gagent_debian || return 1$?
+ [ -d /etc/gentoo ] && proxy_workstation_install_gagent_gentoo || return 2$?
+ return 0
+}
+
+## proxy_workstation_install_gagent
+proxy_workstation_install_gagent_gentoo () {
+ [ -x /usr/bin/qemu-ga -a -x /etc/init.d/qemu-guest-agent ] || \
+ emerge -vb app-emulation/qemu-guest-agent || return 1$?
+ return 0
+}
+
+## proxy_workstation_install_gagent
+proxy_workstation_install_gagent_debian () {
+ [ -e /dev/virtio-ports/org.qemu.guest_agent.0 ] || {
+ echo ERROR: /dev/virtio-ports/org.qemu.guest_agent.0 not found
+ ERROR "check the host xml for "
+ ERROR "or blame Pottyring's systemd"
+ }
+ [ -x /usr/sbin/qemu-ga ] && return 0
+
+ # /mnt/shared/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb
+ if [ -f /var/cache/apt/archives/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb ] ; then
+ dpkg -i /var/cache/apt/archives/qemu-guest-agent_3.1+dfsg-8+deb10u8_amd64.deb
+ fi
+
+ # start guest-service - its failing on the device prerequisite
+ systemctl is-enabled qemu-guest-agent || systemctl enable --now qemu-guest-agent
+ false && \
+ [ -f /lib/systemd/system/qemu-guest-agent.service ] && \
+ [ ! -h /etc/systemd/system/multi-user.target/qemu-guest-agent.service ] && \
+ ln -s /lib/systemd/system/qemu-guest-agent.service \
+ /etc/systemd/system/multi-user.target.wants
+ return 0
+}
+
+## proxy_workstation_test
+proxy_workstation_test () {
+ service qemu-guest-agent status >/dev/null || return 1$?
+ proxy_whonix_test ws || return 2$?
+ return 0
+}
+
+## proxy_workstation_config
+proxy_workstation_config () {
+ proxy_whonix_guest_config || return 1$?
+ proxy_guest_firewall_config || return 2$?
+
+ proxy_ws_whonix_config ws || return 3$?
+
+ variables_defaults
+ [ -n "$GATEWAY_IP_HARDCODED" ] || GATEWAY_IP_HARDCODED="10.152.152.10"
+
+ ## Control Port Filter Proxy Port
+ [ -n "$CONTROL_PORT_FILTER_PROXY_PORT" ] || CONTROL_PORT_FILTER_PROXY_PORT="9051"
+ [ -n "$SOCKS_PORT_TOR_DEFAULT" ] || SOCKS_PORT_TOR_DEFAULT="9050"
+
+ ## Socks Ports for per application circuits.
+ [ -n "$SOCKS_PORT_TB" ] || SOCKS_PORT_TB="9100"
+ [ -n "$SOCKS_PORT_IRC" ] || SOCKS_PORT_IRC="9101"
+ [ -n "$SOCKS_PORT_TORBIRDY" ] || SOCKS_PORT_TORBIRDY="9102"
+ [ -n "$SOCKS_PORT_IM" ] || SOCKS_PORT_IM="9103"
+ [ -n "$SOCKS_PORT_APT_GET" ] || SOCKS_PORT_APT_GET="9104"
+ [ -n "$SOCKS_PORT_GPG" ] || SOCKS_PORT_GPG="9105"
+ [ -n "$SOCKS_PORT_SSH" ] || SOCKS_PORT_SSH="9106"
+ [ -n "$SOCKS_PORT_GIT" ] || SOCKS_PORT_GIT="9107"
+ [ -n "$SOCKS_PORT_SDWDATE" ] || SOCKS_PORT_SDWDATE="9108"
+ [ -n "$SOCKS_PORT_WGET" ] || SOCKS_PORT_WGET="9109"
+ [ -n "$SOCKS_PORT_WHONIXCHECK" ] || SOCKS_PORT_WHONIXCHECK="9110"
+ [ -n "$SOCKS_PORT_BITCOIN" ] || SOCKS_PORT_BITCOIN="9111"
+ [ -n "$SOCKS_PORT_PRIVOXY" ] || SOCKS_PORT_PRIVOXY="9112"
+ [ -n "$SOCKS_PORT_POLIPO" ] || SOCKS_PORT_POLIPO="9113"
+ [ -n "$SOCKS_PORT_WHONIX_NEWS" ] || SOCKS_PORT_WHONIX_NEWS="9114"
+ [ -n "$SOCKS_PORT_TBB_DOWNLOAD" ] || SOCKS_PORT_TBB_DOWNLOAD="9115"
+ [ -n "$SOCKS_PORT_TBB_GPG" ] || SOCKS_PORT_TBB_GPG="9116"
+ [ -n "$SOCKS_PORT_CURL" ] || SOCKS_PORT_CURL="9117"
+ [ -n "$SOCKS_PORT_RSS" ] || SOCKS_PORT_RSS="9118"
+ [ -n "$SOCKS_PORT_TORCHAT" ] || SOCKS_PORT_TORCHAT="9119"
+ [ -n "$SOCKS_PORT_MIXMASTERUPDATE" ] || SOCKS_PORT_MIXMASTERUPDATE="9120"
+ [ -n "$SOCKS_PORT_MIXMASTER" ] || SOCKS_PORT_MIXMASTER="9121"
+ [ -n "$SOCKS_PORT_KDE" ] || SOCKS_PORT_KDE="9122"
+ [ -n "$SOCKS_PORT_GNOME" ] || SOCKS_PORT_GNOME="9123"
+ [ -n "$SOCKS_PORT_APTITUDE" ] || SOCKS_PORT_APTITUDE="9124"
+ [ -n "$SOCKS_PORT_YUM" ] || SOCKS_PORT_YUM="9125"
+ [ -n "$SOCKS_PORT_TBB_DEFAULT" ] || SOCKS_PORT_TBB_DEFAULT="9150"
+
+ return 0
+}
+
+## proxy_workstation_start_bg
+proxy_workstation_start_bg () { proxy_workstation_start $* ; }
+## proxy_workstation_start
+proxy_workstation_start () {
+ local dire=ws
+
+ proxy_workstation_config || return 1$?
+ proxy_whonix_guest_start
+
+ proxy_whonix_polipo_start $dire || \
+ { ret=$? ;echo ERROR: $prog polipo not started ret=$ret; return 4$ret ; }
+
+ return 0
+}
+
+## proxy_workstation_stop
+proxy_workstation_stop () {
+
+ service qemu-guest-agent status >/dev/null \
+ && service qemu-guest-agent stop || return 2$?
+
+ return 0
+}
+
+## proxy_workstation_install
+proxy_workstation_install () {
+
+ proxy_workstation_install_gagent
+ proxy_workstation_fix_getty_timeout
+ proxy_workstation_shutup_verbosity
+ proxy_workstation_install_fstab
+
+ return 0
+}
+
+if [ "$#" -eq 0 ] ; then
+ echo USAGE: $prog $USAGE
+ elif [ "$1" = '-h' ] || [ "$1" = '--help' ] ; then
+ echo USAGE: $prog $USAGE or:
+ grep '^## ' $0 | sed -e 's/^## //'
+
+ elif [ "$1" = config -o "$1" = install ] ; then
+ proxy_workstation_install || return 3$?
+
+ elif [ "$1" = verify -o "$1" = test ] ; then
+ proxy_workstation_test || return 4$?
+
+ elif [ "$1" = start_bg -o "$1" = start -o "$1" = stop ] ; then
+ proxy_workstation_$1 || return 5$?
+
+ else
+ eval "$@"
+ exit $?
+
+ fi
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_host-firewall.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_host-firewall.bash
new file mode 100755
index 0000000..3dde358
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_host-firewall.bash
@@ -0,0 +1,769 @@
+#!/bin/bash
+# -*-mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+prog=$( basename $0 .bash )
+PREFIX=/usr/local
+ROLE=proxy
+. /usr/local/bin/usr_local_base.bash || exit 2
+
+VER=10
+
+set -o pipefail || { ERROR use bash ; exit 1 ; } #! illegal option
+
+. /usr/local/bin/proxy_ping_lib.bash || exit 2
+
+# unlike the original script, this just generates the rules
+# and writes the to an output file
+OUT=/tmp/I4$$.iptables
+cp /dev/null $OUT4
+ip4_tables () {
+ # now unused
+ echo "$@" >> $OUT4
+ return 0
+}
+ip6_tables () {
+ [ -d /proc/sys/net/ipv6/ ] || return 0
+ echo "$@" >> $OUT6
+ return 0
+}
+
+. /usr/local/bin/proxy_ping_lib.bash || exit 2
+
+# sysctl net.ipv4.conf.all.accept_redirects != 1 in /etc/sysctl.d/70_testforge_harden_lynis.conf
+
+[ -f $PREFIX/etc/testforge/testforge.bash ] && . /usr/local/etc/testforge/testforge.bash
+# || { echo >&2 ERROR: $prog "$PREFIX/etc/testforge/testforge.bash" ; exit 3 ; }
+
+if [ "$#" -eq 1 -a "$1" = test ] ; then
+ bash /usr/local/bin/proxy_ping_test.bash 2>&1| grep ' 0% packet loss' \
+ || { echo ERROR: ping ; exit 4 ; }
+ exit 0
+ fi
+
+#set -- -x
+# leave empty for debugging
+[ "$DEBUG" = "1" ] && HUSH="" || HUSH="#D#"
+WHONIX_HOST=1
+# leave it in anyway
+LOCAL_TOR=1
+
+if [ -f /etc/firewall.conf.block ] ; then
+ BLOCK_IPS=`cat /etc/firewall.conf.block`
+else
+ BLOCK_IPS="37.191.192.147 51.79.22.22"
+fi
+
+NOW=$( date +%c )
+
+PROXY_WLAN=$( proxy_get_if )
+[ $? -eq 0 ] || { echo ERROR: " error getting device $?" ; exit 2 ; }
+[ -n "$PROXY_WLAN" ] || { echo ERROR: " error getting device $PROXY_WLAN" ; exit 3 ; }
+
+## External interface
+[ -n "$WLAN_IF" ] || WLAN_IF="$PROXY_WLAN"
+[ -n "$IP" ] && WLAN_NET=$( echo $IP|sed -e 's/\.[1-9][0-9]*$/.0/' )/24
+[ -n "$PROXY_WLAN_GW" ] && PROXY_WLAN_GW=$( echo $IP|sed -e 's/\.[1-9][0-9]*$/.1/' )
+
+[ -z "$PRIV_NTP_OWNER" ] && PRIV_NTP_OWNER=ntp
+PRIV_NTP_GID=$( grep ^$PRIV_NTP_OWNER /etc/passwd|cut -d: -f 4 )
+[ -z "$PRIV_TOR_OWNER" ] && PRIV_TOR_OWNER=tor
+PRIV_TOR_GID=$( grep ^$PRIV_TOR_OWNER /etc/passwd|cut -d: -f 4 )
+[ -z "$PRIV_BIN_OWNER" ] && PRIV_BIN_OWNER=bin
+PRIV_BIN_GID=$( grep ^$PRIV_BIN_OWNER /etc/passwd|cut -d: -f 4 )
+[ $LOCAL_TOR -ne 0 ] && CLEARNET_GIDS="$PRIV_BIN_GID $PRIV_TOR_GID" || CLEARNET_GIDS="$PRIV_BIN_GID"
+
+[ -z "$PRIV_TOR_SOCKSPORT" ] && PRIV_TOR_SOCKSPORT=9050
+[ -z "$PRIV_TOR_CONTROLPORT" ] && PRIV_TOR_CONTROLPORT=9051
+[ -z "$PRIV_TOR_DNSSPORT" ] && PRIV_TOR_DNSSPORT=9053
+[ -z "$PRIV_POLIPO_PROXYPORT" ] && PRIV_POLIPO_PROXYPORT=3128
+[ -z "$PRIV_TOR_PROXYPORT" ] && PRIV_TOR_PROXYPORT=9128
+[ -z "$PRIV_NAT_TRANSPORT" ] && PRIV_NAT_TRANSPORT="9040"
+PRIV_NAT_TRANSHOST="$PROXY_WLAN"
+
+SSH_SERVICE=22
+BOOTPC_SERVICE=68
+BOOTPS_SERVICE=67
+[ -z "$PRIV_SERVICE_NTPPORT" ] && PRIV_SERVICE_NTPPORT=123
+NETBIOSNS_SERVICE=137
+NETBIOSDG_SERVICE=138
+NETBIOSSS_SERVICE=139
+
+WLAN_ALLOW_SERVICES="$PRIV_SERVICE_NTPPORT $BOOTPC_SERVICE $BOOTPS_SERVICE"
+WLAN_DROP_SERVICES="$NETBIOSNS_SERVICE $NETBIOSDG_SERVICE $NETBIOSSS_SERVICE"
+NAT_SERVICES_TO_LO_TCP=""
+EXT_ALLOW_SERVICES_IN_TCP="$SSH_SERVICE $PRIV_TOR_PROXYPORT $PRIV_TOR_SOCKSPORT 7001"
+EXT_ALLOW_SERVICES_IN_UDP="$PRIV_TOR_DNSSPORT"
+# $PRIV_NAT_TRANSPORT
+EXT_ALLOW_SERVICES_OUT_TCP="$SSH_SERVICE $PRIV_TOR_PROXYPORT $PRIV_TOR_SOCKSPORT 7001"
+EXT_ALLOW_SERVICES_OUT_UDP="$PRIV_TOR_DNSSPORT"
+
+EXT_VNET=virbr1
+PRIV_WHONIX_EXTERNAL_NET="10.0.2.0/24"
+# 10.152.152.10 gateway
+# 10.152.152.11 work
+# 10.16.238.0.0
+INT_VNET=virbr2
+# gateway is 10.152.152.10
+PRIV_WHONIX_INTERNAL_NET=10.152.152.0/24
+PRIVATE_NET="" # 192.168.1.0/24
+
+## Accept outgoing connections to local network, Whonix-Workstation and VirtualBox,
+## unless VPN_FIREWALL mode is enabled. Enabled By DEFAULT.
+VPN_FIREWALL="0"
+LIBVIRT_FW=1 # 0 or 1 or 2
+# I think this is still needed - dnsmasq is on 127:
+LOCALHOST_DNS=1
+HOST_ALLOW_INCOMING_ICMP=1
+HOST_ALLOW_OUTGOING_ICMP=1
+
+## Accept outgoing connections to local network, Whonix-Workstation and VirtualBox,
+## unless VPN_FIREWALL mode is enabled. Enabled By DEFAULT.
+VPN_FIREWALL="0"
+LIBVIRT_FW=1 # 0 or 1 or 2
+
+#override
+HOST_nat_TRANS="";PRIV_NAT_TRANSPORT="";PRIV_NAT_TRANSHOST=""
+
+INFO "Loading Whonix firewall for $PROXY_WLAN IP=$IP LIBVIRT_FW=$LIBVIRT_FW"
+
+if ifconfig -a | grep -q $EXT_VNET && proxy_virsh list | grep Whonix-Gateway ; then
+ # on the host - does this work?
+ ifconfig -a | grep -q inet # || ifconfig $EXT_VNET 10.0.2.2 up
+ HOST_WHONIX_GATE=1
+ fi
+if ifconfig -a | grep -q $INT_VNET && proxy_virsh list | grep Whonix-Workstation ; then
+ # on the host
+ ifconfig -a | grep -q inet #? || ifconfig $INT_VNET 10.152.152.10 up
+ HOST_WHONIX_WORK=1
+ fi
+HOST_WHONIX_GATE=1
+HOST_WHONIX_WORK=1
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+###########################
+## debugging
+###########################
+
+#set -x
+
+###########################
+## error_handler
+###########################
+
+error_handler() {
+ echo "##################################################"
+ echo "Whonix firewall script failed!" see $OUT4
+ echo "##################################################"
+ exit 1
+}
+
+#? trap "error_handler" ERR
+
+###########################
+## source config folder
+###########################
+
+shopt -s nullglob || exit 1
+for i in /etc/whonix_firewall.d/*.conf /usr/local/etc/whonix_firewall.d/*.conf; do
+ bash_n_exit_code="0"
+ bash_n_output="$(bash -n "$i" 2>&1)" || { bash_n_exit_code="$?" ; true; };
+ if [ ! "$bash_n_exit_code" = "0" ]; then
+ ERROR "Invalid config file: $i
+bash_n_exit_code: $bash_n_exit_code
+bash_n_output:
+$bash_n_output" >&2
+ exit 1
+ fi
+ source "$i"
+done
+
+###########################
+## comments
+###########################
+
+## --reject-with
+## http://ubuntuforums.org/showthread.php?p=12011099
+
+## Set to icmp-admin-prohibited because icmp-port-unreachable caused
+## confusion. icmp-port-unreachable looks like a bug while
+## icmp-admin-prohibited hopefully makes clear it is by design.
+
+###########################
+## /usr/bin/whonix_firewall
+###########################
+
+###########################
+## interfaces
+###########################
+
+INFO "Loading Whonix firewall for $WLAN_IF"
+
+###########################
+DBUG NON_TOR_GATEWAY
+###########################
+
+#me these defaults should be in the .conf files
+## Destinations you do not routed through VPN, only for Whonix-Gateway.
+## 10.0.2.2/24: VirtualBox DHCP
+[ -n "$NON_TOR_GATEWAY" ] || NON_TOR_GATEWAY="$PRIVATE_NET $WLAN_NET $PRIV_WHONIX_INTERNAL_NET $PRIV_WHONIX_EXTERNAL_NET"
+
+################
+## VPN related #
+################
+
+## Space separated list of VPN servers,
+## which Whonix-Gateway is allowed to connect to.
+[ -n "$VPN_SERVERS" ] || VPN_SERVERS="198.252.153.26"
+VPN_SERVERS=
+
+[ -n "$VPN_INTERFACE" ] || VPN_INTERFACE="tun0"
+VPN_INTERFACE=
+
+## Destinations you do not routed through VPN, only for Whonix-Gateway.
+## $PRIV_WHONIX_EXTERNAL_NET: VirtualBox DHCP
+[ -n "$LOCAL_NET" ] || LOCAL_NET="$PRIVATE_NET $WLAN_NET $PRIV_WHONIX_INTERNAL_NET $PRIV_WHONIX_EXTERNAL_NET"
+
+###########################
+DBUG IPv4 DEFAULTS
+###########################
+lsmod | grep -q iptable_filter || modprobe iptable_filter
+
+###########################
+DBUG IPv4 PREPARATIONS
+###########################
+# FixMe: nf or xt?
+lsmod | grep -q nf_nat || modprobe nf_nat
+lsmod | grep -q iptable_filter || modprobe iptable_filter
+lsmod | grep -q iptable_mangle || modprobe iptable_mangle
+
+## Flush old rules. We now let the caller do that when it uses the rules
+# mangle comes before filter, before nat
+# iptables -t mangle -F
+# iptables -t mangle -X
+# iptables -t filter -F
+# iptables -t filter -X
+# iptables -t nat -F
+# iptables -t nat -X
+
+DBUG MANGLE COMES BEFORE FILTER
+
+cat >> $OUT4 << EOF
+# -*-mode: conf[Space]; tab-width: 8; coding: utf-8-unix -*-
+# firewall.bash.libvirt.$VER
+*mangle
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+EOF
+
+[ $LIBVIRT_FW -ge 1 ] && \
+ cat >> $OUT4 << EOF
+:LIBVIRT_PRT - [0:0]
+${HUSH}-A INPUT -j LOG --log-prefix "iptables_mangle_END-i: " --log-uid
+EOF
+
+cat >> $OUT4 << EOF
+COMMIT
+EOF
+
+cat >> $OUT4 << EOF
+
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+EOF
+
+cat >> $OUT4 << EOF
+:LIBVIRT_PRT - [0:0]
+EOF
+
+# iptables: No chain/target/match by that name.
+false && \
+[ $LOCALHOST_DNS -gt 0 ] && \
+ cat >> $OUT4 << EOF
+
+# was ! -o lo
+# let resolve.conf redirect to lo - this rule cannot be removed
+#-A OUTPUT -o $WLAN_IF -p tcp --dport $PRIV_SERVICE_DNSPORT -j DNAT --to-destination 127.0.0.1:$PRIV_SERVICE_DNSPORT
+#-A OUTPUT -o $WLAN_IF -p udp --dport $PRIV_SERVICE_DNSPORT -j DNAT --to-destination 127.0.0.1:$PRIV_SERVICE_DNSPORT
+EOF
+#?
+for elt in $NAT_SERVICES_TO_LO_TCP ; do
+ cat >> $OUT4 << EOF
+-A OUTPUT ! -o lo -p tcp --dport $PRIV_SERVICE_DNSPORT -j DNAT --to-destination 127.0.0.1:$elt
+EOF
+done
+
+if [ $LOCAL_TOR -ne 0 -a "$PRIV_NAT_TRANSPORT" != "" -a "$PRIV_NAT_TRANSHOST" != "" -a "$PRIV_NAT_VIRTUAL_NET" != "" ] ; then
+ NO=""
+else
+ NO="#"
+fi
+cat >> $OUT4 << EOF
+
+# .onion mapped addresses redirection to Tor.
+${NO}-A OUTPUT -d $PRIV_NAT_VIRTUAL_NET -p tcp -j DNAT --to-destination ${PRIV_NAT_TRANSHOST}:$PRIV_NAT_TRANSPORT
+EOF
+
+if [ -n "$HOST_nat_TRANS" -a "$PRIV_NAT_TRANSPORT" != "" -a "$PRIV_NAT_TRANSHOST" != "" ] ; then
+ cat >> $OUT4 << EOF
+
+# nat REDIRECT ALL REMAINING TCP TRAFFIC TO TOR.
+# was ! -o lo
+-A OUTPUT -o $WLAN_IF -j LOG --log-uid --log-prefix "iptables_nat_TRANS: "
+-A OUTPUT -o $WLAN_IF -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j DNAT --to-destination ${PRIV_NAT_TRANSHOST}:$PRIV_NAT_TRANSPORT
+EOF
+ fi
+
+cat >> $OUT4 << EOF
+## Log.
+${HUSH}-A INPUT -j LOG --log-prefix "iptables_nat_END-i: " --log-uid
+EOF
+
+lsmod | grep -q nft_masq || modprobe nft_masq
+#4 lsmod | grep -q xt_MASQUERADE|| modprobe xt_MASQUERADE
+
+[ $LIBVIRT_FW -ge 1 ] && \
+ cat >> $OUT4 << EOF
+-A POSTROUTING -j LIBVIRT_PRT
+-A LIBVIRT_PRT -s $PRIV_WHONIX_EXTERNAL_NET -d 224.0.0.0/24 -j RETURN
+-A LIBVIRT_PRT -s $PRIV_WHONIX_EXTERNAL_NET -d 255.255.255.255/32 -j RETURN
+-A LIBVIRT_PRT -s $PRIV_WHONIX_EXTERNAL_NET ! -d $PRIV_WHONIX_EXTERNAL_NET -p tcp -j MASQUERADE --to-ports 1024-65535
+-A LIBVIRT_PRT -s $PRIV_WHONIX_EXTERNAL_NET ! -d $PRIV_WHONIX_EXTERNAL_NET -p udp -j MASQUERADE --to-ports 1024-65535
+-A LIBVIRT_PRT -s $PRIV_WHONIX_EXTERNAL_NET ! -d $PRIV_WHONIX_EXTERNAL_NET -j MASQUERADE
+EOF
+
+cat >> $OUT4 << EOF
+COMMIT
+EOF
+
+lsmod | grep -q nf_conntrack || modprobe nf_conntrack
+lsmod | grep -q xt_state || modprobe xt_state
+
+cat >> $OUT4 << EOF
+# SET SECURE DEFAULTS FOR INPUT FILTER
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT DROP [0:0]
+EOF
+
+[ $LIBVIRT_FW -ge 1 ] && \
+ cat >> $OUT4 << EOF
+:LIBVIRT_FWI - [0:0]
+:LIBVIRT_FWO - [0:0]
+:LIBVIRT_FWX - [0:0]
+:LIBVIRT_INP - [0:0]
+:LIBVIRT_OUT - [0:0]
+
+${HUSH}-A INPUT -j LOG --log-prefix "iptables_filter_BEGIN-i: firewall.bash.libvirt.$VER" --log-uid
+
+# blocks wlan
+EOF
+
+for elt in $BLOCK_IPS ; do
+ cat >> $OUT4 << EOF
+-A INPUT -s $elt -p tcp -j DROP
+EOF
+ done
+
+DBUG IPv4 DROP INVALID INCOMING PACKAGES
+
+cat >> $OUT4 << EOF
+
+## DROP MARTIANS
+## https://www.cyberciti.biz/faq/linux-log-suspicious-martian-packets-un-routable-source-addresses/
+-A INPUT -i $WLAN_IF -s 10.0.0.0/8 -j LOG --log-prefix "iptables_martian_DROP SPOOF A: "
+-A INPUT -i $WLAN_IF -s 172.16.0.0/12 -j LOG --log-prefix "iptables_martian_DROP SPOOF B: "
+-A INPUT -i $WLAN_IF -s 192.168.0.0/16 -j LOG --log-prefix "iptables_martian_DROP SPOOF C: "
+-A INPUT -i $WLAN_IF -s 224.0.0.0/4 -j LOG --log-prefix "iptables_martian_DROP MULTICAST D: "
+-A INPUT -i $WLAN_IF -s 240.0.0.0/5 -j LOG --log-prefix "iptables_martian_DROP SPOOF E: "
+-A INPUT -i $WLAN_IF -d 127.0.0.0/8 -j LOG --log-prefix "iptables_martian_DROP LOOPBACK: "
+
+-A INPUT -i $WLAN_IF -s 10.0.0.0/8 -j DROP
+-A INPUT -i $WLAN_IF -s 172.16.0.0/12 -j DROP
+-A INPUT -i $WLAN_IF -s 192.168.0.0/16 -j DROP
+-A INPUT -i $WLAN_IF -s 224.0.0.0/4 -j DROP
+-A INPUT -i $WLAN_IF -s 240.0.0.0/5 -j DROP
+-A INPUT -i $WLAN_IF -d 127.0.0.0/8 -j DROP
+
+## DROP INVALID
+-A INPUT -m conntrack --ctstate INVALID -j DROP
+-A INPUT -m state --state INVALID -j DROP
+
+## DROP INVALID SYN PACKETS
+-A INPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
+-A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
+-A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
+
+## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
+-A INPUT -f -j DROP
+## DROP INCOMING MALFORMED XMAS PACKETS
+-A INPUT -p tcp --tcp-flags ALL ALL -j DROP
+## DROP INCOMING MALFORMED NULL PACKETS
+-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
+EOF
+
+cat >> $OUT4 << EOF
+## Traffic on the loopback interface is accepted.
+-A INPUT -i lo -j ACCEPT
+## Established incoming connections are accepted.
+-A INPUT -m state --state ESTABLISHED -j ACCEPT
+EOF
+
+## All incoming connections are dropped by default anyway, but should a user
+## allow incoming ports (such as for incoming SSH or FlashProxy), ICMP should
+## still be dropped to filter for example ICMP time stamp requests.
+if [ "$HOST_ALLOW_INCOMING_ICMP" != "1" ]; then
+ DBUG Drop all incoming ICMP traffic by default.
+ cat >> $OUT4 << EOF
+-A INPUT -i $WLAN_IF -p icmp -j LOG --log-prefix "IPTABLES_icmp_DROP-i: " --log-uid
+-A INPUT -i $WLAN_IF -p icmp -j DROP
+EOF
+ else
+ DBUG Accept all incoming ICMP traffic by default.
+ cat >> $OUT4 << EOF
+### this is required for outgoing pings
+-A INPUT -i $WLAN_IF -p icmp -j LOG --log-prefix "iptables_icmp_ACCEPT-i: " --log-uid
+-A INPUT -i $WLAN_IF -p icmp -j ACCEPT
+EOF
+fi
+
+## Allow all incoming connections on the virtual VPN network interface,
+## when VPN_FIREWALL mode is enabled. DISABLED BY DEFAULT.
+if [ "$VPN_FIREWALL" = "1" ]; then
+ cat >> $OUT4 << EOF
+ -A INPUT -i "$VPN_INTERFACE" -j ACCEPT
+EOF
+fi
+
+#root@Flati:# su -c '/usr/sbin/ntpdate 132.163.97.3' -s /bin/sh ntp
+#12 Nov 21:39:14 ntpdate[4085]: bind() fails: Permission denied
+#root@Flati:# ls -l `which ntpdate`
+#-rwxr-sr-x 1 root ntp 85016 Jun 29 17:18 /usr/sbin/ntpdate
+
+lsmod | grep -q xt_owner || modprobe xt_owner
+cat >> $OUT4 << EOF
+# these are NOT needed
+#!-A INPUT -i $WLAN_IF -m owner --gid-owner $PRIV_NTP_GID -p udp --sport $PRIV_SERVICE_NTPPORT -j LOG --log-uid --log-prefix "iptables_${PRIV_SERVICE_NTPPORT}_ACCEPT-o: "
+#!-A INPUT -i $WLAN_IF -m owner --gid-owner $PRIV_NTP_GID -p udp --sport $PRIV_SERVICE_NTPPORT -j ACCEPT
+#!-A INPUT -i $WLAN_IF -m owner --uid-owner 0 -p udp --sport $PRIV_SERVICE_NTPPORT -j LOG --log-uid --log-prefix "iptables_${PRIV_SERVICE_NTPPORT}_ACCEPT-o: "
+#!-A INPUT -i $WLAN_IF -m owner --uid-owner 0 -p udp --sport $PRIV_SERVICE_NTPPORT -j ACCEPT
+EOF
+
+DBUG clearnet gids is allowed to connect any outside target $CLEARNET_GIDS
+for elt in $CLEARNET_GIDS ; do
+ cat >> $OUT4 << EOF
+# these are NOT needed
+#!-A INPUT -i $WLAN_IF -p tcp -m owner --gid-owner $elt -j ACCEPT
+EOF
+done
+
+cat >> $OUT4 << EOF
+#?# let dhcp through?
+#?-A INPUT -p udp --sport $BOOTPC_SERVICE -j ACCEPT
+#?-A INPUT -p udp --sport $BOOTPS_SERVICE -j ACCEPT
+EOF
+# was ACCEPT - try DROP - should be up in mangle as REJECT?
+for elt in $WLAN_DROP_SERVICES ; do
+ cat >> $OUT4 << EOF
+-A INPUT -i $WLAN_IF -p udp --sport $elt -j DROP
+EOF
+done
+
+if [ "$HOST_ALLOW_INCOMING_ICMP" != "1" ]; then
+ DBUG Drop all incoming ICMP traffic by default.
+ cat >> $OUT4 << EOF
+-A INPUT -i $EXT_VNET -p icmp -j LOG --log-prefix "IPTABLES_icmp_DROP-i: " --log-uid
+-A INPUT -i $EXT_VNET -p icmp -j DROP
+EOF
+ else
+ DBUG Accept all incoming ICMP traffic by default.
+ cat >> $OUT4 << EOF
+### this is required for outgoing pings
+-A INPUT -i $EXT_VNET -p icmp -j LOG --log-prefix "iptables_icmp_ACCEPT-i: " --log-uid
+-A INPUT -i $EXT_VNET -p icmp -j ACCEPT
+EOF
+fi
+
+DBUG use the gateway as a proxy box, including ssh INPUT
+# works -i virbr1 and -sport not -dport
+# -A INPUT -i virbr1 -p tcp --sport 22 -j LOG --log-uid --log-prefix "iptables_22_ACCEPT-i: "
+for elt in $EXT_ALLOW_SERVICES_IN_TCP ; do
+ cat >> $OUT4 << EOF
+-A INPUT -i $EXT_VNET -p tcp --sport $elt -j LOG --log-uid --log-prefix "iptables_${elt}_ACCEPT-i: "
+-A INPUT -i $EXT_VNET -p tcp --sport $elt -j ACCEPT
+EOF
+done
+for elt in $EXT_ALLOW_SERVICES_IN_UDP ; do
+ cat >> $OUT4 << EOF
+-A INPUT -i $EXT_VNET -p udp --sport $elt -j LOG --log-uid --log-prefix "iptables_${elt}_ACCEPT-i: "
+-A INPUT -i $EXT_VNET -p udp --sport $elt -j ACCEPT
+EOF
+done
+
+## Reject anything not explicitly allowed above.
+## Drop is better than reject here, because we do not want to reveal it's a Whonix-Gateway.
+## (In case someone running Whonix-Gateway on bare metal.)
+cat >> $OUT4 << EOF
+-A INPUT -j LOG --log-prefix "IPTABLES_filter_DROP-i: " --log-uid
+-A INPUT -j DROP
+EOF
+
+# FixMe: DROP?
+[ may = be ] && \
+cat >> $OUT4 << EOF
+#?-A FORWARD -j LOG --log-prefix "IPTABLES_forward_DROP-i: " --log-uid
+#?-A FORWARD -j REJECT --reject-with icmp-admin-prohibited
+EOF
+
+[ $LIBVIRT_FW -ge 1 ] && \
+ cat >> $OUT4 << EOF
+-A INPUT -j LIBVIRT_INP
+
+
+
+-A FORWARD -j LIBVIRT_FWX
+-A FORWARD -j LIBVIRT_FWI
+-A FORWARD -j LIBVIRT_FWO
+EOF
+###########################
+## IPv4 OUTPUT
+###########################
+
+cat >> $OUT4 << EOF
+## Traffic on the loopback interface is accepted.
+-A OUTPUT -o lo -j ACCEPT
+
+## Existing connections are accepted.
+-A OUTPUT -m state --state ESTABLISHED -j ACCEPT
+EOF
+
+## Allow outgoing traffic on VPN interface,
+## if VPN_FIREWALL mode is enabled.
+## DISABLED BY DEFAULT.
+if [ "$VPN_FIREWALL" = "1" ]; then
+ cat >> $OUT4 << EOF
+-A OUTPUT -o "$VPN_INTERFACE" -j ACCEPT
+EOF
+fi
+
+## Connections to VPN servers are allowed,
+## when VPN_FIREWALL mode is enabled.
+## DISABLED BY DEFAULT.
+if [ "$VPN_FIREWALL" = "1" ]; then
+ for SERVER in $VPN_SERVERS; do
+cat >> $OUT4 << EOF
+-A OUTPUT -d $SERVER -j ACCEPT
+EOF
+ done
+fi
+
+## Drop all incoming ICMP traffic by default.
+## All incoming connections are dropped by default anyway, but should a user
+## allow incoming ports (such as for incoming SSH or FlashProxy), ICMP should
+## still be dropped to filter for example ICMP time stamp requests.
+if [ "$HOST_ALLOW_OUTGOING_ICMP" != "1" ]; then
+ DBUG Drop all outcoming ICMP traffic by default.
+cat >> $OUT4 << EOF
+-A OUTPUT -o $WLAN_IF -p icmp -j LOG --log-prefix "IPTABLES_icmp_DROP-o: " --log-uid
+-A OUTPUT -o $WLAN_IF -p icmp -j DROP
+EOF
+ else
+ DBUG Accept all outcoming ICMP traffic by default.
+cat >> $OUT4 << EOF
+-A OUTPUT -o $WLAN_IF -p icmp -j LOG --log-prefix "iptables_icmp_ACCEPT-o: " --log-uid
+-A OUTPUT -o $WLAN_IF -p icmp -j ACCEPT
+EOF
+fi
+## Accept outgoing connections to local network, Whonix-Workstation and VirtualBox,
+## unless VPN_FIREWALL mode is enabled. ENABLED BY DEFAULT.
+#? WHY?!
+if [ "$VPN_FIREWALL" != "1" ]; then
+ for NET in $NON_TOR_GATEWAY; do
+cat >> $OUT4 << EOF
+#?-A OUTPUT -d $NET -j ACCEPT
+EOF
+ done
+fi
+
+# required sufficient works - not for user ntp
+[ -n "$PRIV_NTP_GID" ] && \
+ cat >> $OUT4 << EOF
+# The ntp user is allowed to connect to services listening on the ntp port...
+# If root runs ntpdate manually you will see requests to port 53 UID=0
+-A OUTPUT -o $WLAN_IF -m owner --gid-owner $PRIV_NTP_GID -p udp --dport $PRIV_SERVICE_NTPPORT -j LOG --log-uid --log-prefix "iptables_${PRIV_SERVICE_NTPPORT}_ACCEPT-o: "
+-A OUTPUT -o $WLAN_IF -m owner --gid-owner $PRIV_NTP_GID -p udp --dport $PRIV_SERVICE_NTPPORT -j ACCEPT
+-A OUTPUT -o $WLAN_IF -m owner --uid-owner 0 -p udp --dport $PRIV_SERVICE_NTPPORT -j LOG --log-uid --log-prefix "iptables_${PRIV_SERVICE_NTPPORT}_ACCEPT-o: "
+-A OUTPUT -o $WLAN_IF -m owner --uid-owner 0 -p udp --dport $PRIV_SERVICE_NTPPORT -j ACCEPT
+EOF
+
+cat >> $OUT4 << EOF
+# ssh - specifically forbid ssh out the wlan
+-A OUTPUT -o $WLAN_IF -p tcp --dport $SSH_SERVICE -j LOG --log-uid --log-prefix "IPTABLES_ssh_REJECT-o: "
+-A OUTPUT -o $WLAN_IF -p tcp --dport $SSH_SERVICE -j REJECT --reject-with icmp-port-unreachable
+EOF
+
+DBUG clearnet gids is allowed to connect any outside target $CLEARNET_GIDS
+for elt in $CLEARNET_GIDS ; do
+ cat >> $OUT4 << EOF
+# necessary and sufficient
+-A OUTPUT -o $WLAN_IF -m owner --gid-owner $elt -j ACCEPT
+EOF
+done
+
+if [ "$HOST_ALLOW_OUTGOING_ICMP" == "1" ]; then
+ cat >> $OUT4 << EOF
+-A OUTPUT -o $EXT_VNET -p icmp -j LOG --log-prefix "iptables_icmp_ACCEPT-o: " --log-uid
+-A OUTPUT -o $EXT_VNET -p icmp -j ACCEPT
+EOF
+fi
+
+DBUG use the gateway as a proxy box, including ssh OUTPUT host to guest
+# works -i virbr1 and -sport not -dport
+# -A INPUT -i virbr1 -p tcp --sport 22 -j LOG --log-uid --log-prefix "iptables_22_ACCEPT-i: "
+for elt in $EXT_ALLOW_SERVICES_OUT_TCP ; do
+ cat >> $OUT4 << EOF
+-A OUTPUT -o $EXT_VNET -p tcp --dport $elt -j LOG --log-uid --log-prefix "iptables_${elt}_ACCEPT-o: "
+-A OUTPUT -o $EXT_VNET -p tcp --dport $elt -j ACCEPT
+EOF
+done
+for elt in $EXT_ALLOW_SERVICES_OUT_UDP ; do
+ cat >> $OUT4 << EOF
+-A OUTPUT -o $EXT_VNET -p udp --dport $elt -j LOG --log-uid --log-prefix "iptables_${elt}_ACCEPT-o: "
+-A OUTPUT -o $EXT_VNET -p udp --dport $elt -j ACCEPT
+EOF
+done
+
+cat >> $OUT4 << EOF
+#??-A OUTPUT -p udp -m udp --sport 68 --dport 67 -j RETURN
+#?-A OUTPUT -p udp -m udp --sport 68 --dport 67 -j ACCEPT
+EOF
+
+if [ $LIBVIRT_FW -ge 1 ] ; then
+ cat >> $OUT4 << EOF
+-A OUTPUT -j LIBVIRT_OUT
+# block virbr1
+EOF
+ for elt in $BLOCK_IPS ; do
+ cat >> $OUT4 << EOF
+-A LIBVIRT_FWI -s $elt -p tcp -j DROP
+EOF
+ done
+ cat >> $OUT4 << EOF
+-A LIBVIRT_FWI -o $EXT_VNET -j LOG --log-uid --log-prefix "IPTABLES_FWI_REJECT-o: "
+-A LIBVIRT_FWI -o $INT_VNET -j REJECT --reject-with icmp-port-unreachable
+
+-A LIBVIRT_FWI -d $PRIV_WHONIX_EXTERNAL_NET -o $EXT_VNET -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+
+-A LIBVIRT_FWI -o $EXT_VNET -j LOG --log-uid --log-prefix "IPTABLES_FWI_REJECT-o: "
+#blocks
+-A LIBVIRT_FWI -o $EXT_VNET -j REJECT --reject-with icmp-port-unreachable
+
+-A LIBVIRT_FWO -i $INT_VNET -j LOG --log-uid --log-prefix "IPTABLES_FWO_REJECT-i: "
+-A LIBVIRT_FWO -i $INT_VNET -j REJECT --reject-with icmp-port-unreachable
+
+-A LIBVIRT_FWO -s $PRIV_WHONIX_EXTERNAL_NET -i $EXT_VNET -j ACCEPT
+
+-A LIBVIRT_FWO -i $EXT_VNET -j LOG --log-uid --log-prefix "IPTABLES_FWO_REJECT-i: "
+-A LIBVIRT_FWO -i $EXT_VNET -j REJECT --reject-with icmp-port-unreachable
+
+-A LIBVIRT_FWX -i $INT_VNET -o $INT_VNET -j ACCEPT
+-A LIBVIRT_FWX -i $EXT_VNET -o $EXT_VNET -j ACCEPT
+
+# FixMe: sic this is what libvirt did -i --dport
+# FixMe: I will disable them as I dont think theyre needed or wanted
+#no -A LIBVIRT_INP -i $INT_VNET -p udp --dport 53 -j ACCEPT
+#no -A LIBVIRT_INP -i $INT_VNET -p tcp --dport 53 -j ACCEPT
+#no -A LIBVIRT_INP -i $INT_VNET -p udp --dport 67 -j ACCEPT
+#no -A LIBVIRT_INP -i $INT_VNET -p tcp --dport 67 -j ACCEPT
+#no
+#no # FixMe:sic this is what libvirt did -i --dport
+#no -A LIBVIRT_INP -i $EXT_VNET -p udp --dport 53 -j ACCEPT
+#no -A LIBVIRT_INP -i $EXT_VNET -p tcp --dport 53 -j ACCEPT
+#no -A LIBVIRT_INP -i $EXT_VNET -p udp --dport 67 -j ACCEPT
+#no -A LIBVIRT_INP -i $EXT_VNET -p tcp --dport 67 -j ACCEPT
+#no
+#no -A LIBVIRT_OUT -o $INT_VNET -p udp --dport 53 -j ACCEPT
+#no -A LIBVIRT_OUT -o $INT_VNET -p tcp --dport 53 -j ACCEPT
+#no -A LIBVIRT_OUT -o $INT_VNET -p udp --dport 68 -j ACCEPT
+#no -A LIBVIRT_OUT -o $INT_VNET -p tcp --dport 68 -j ACCEPT
+#no
+#no -A LIBVIRT_OUT -o $EXT_VNET -p udp --dport 53 -j ACCEPT
+#no -A LIBVIRT_OUT -o $EXT_VNET -p tcp --dport 53 -j ACCEPT
+#no -A LIBVIRT_OUT -o $EXT_VNET -p udp --dport 68 -j ACCEPT
+#no -A LIBVIRT_OUT -o $EXT_VNET -p tcp --dport 68 -j ACCEPT
+EOF
+fi
+
+cat >> $OUT4 << EOF
+# added
+-A LIBVIRT_FWX -o $EXT_VNET -s 10.0.2.2 -d 10.0.2.15 -j ACCEPT
+${HUSH}-A OUTPUT -j LOG --log-uid --log-prefix "IPTABLES_filter_DROP-o: "
+${HUSH}-A OUTPUT -j DROP
+EOF
+
+cat >> $OUT4 << EOF
+COMMIT
+# Generated $NOW
+EOF
+
+# IPV6
+if [ ! -e /proc/net/if_inet6 ] ; then
+ [ -f /etc/sysctl.d/70_testforge_harden_lynis.conf ] && \
+ sed -i -e 's/^net.ipv6.conf/#net.ipv6.conf/' /etc/sysctl.d/70_testforge_harden_lynis.conf
+ else
+ # nft_reject nft_reject_inet nf_reject_ipv4 nft_reject_ipv4 ipt_REJECT
+ for elt in nf_reject_ipv6 nft_reject_ipv6 ip6t_REJECT ; do
+ lsmod | grep -q $elt || modprobe $elt
+ done
+
+ sed -i -e 's/^#net.ipv6.conf/net.ipv6.conf/' /etc/sysctl.d/70_testforge_harden_lynis.conf
+ # ACTIVE
+ ## Log.
+ proxy_ip6tables -A INPUT -j LOG --log-prefix "IPTABLES_Whonix blocked input6: "
+ proxy_ip6tables -A OUTPUT -j LOG --log-prefix "IPTABLES_Whonix blocked output6: "
+ proxy_ip6tables -A FORWARD -j LOG --log-prefix "IPTABLES_Whonix blocked forward6: "
+
+ ## Drop/reject all other traffic.
+ proxy_ip6tables -A INPUT -j DROP
+ #### --reject-with icmp-admin-prohibited not supported by proxy_ip6tables
+ proxy_ip6tables -A OUTPUT -j REJECT
+ ## --reject-with icmp-admin-prohibited not supported by proxy_ip6tables
+ proxy_ip6tables -A FORWARD -j REJECT
+fi
+
+
+###########################
+## End
+###########################
+
+proxy_iptables_restore -tv < $OUT4 >/tmp/I$$.log 2>&1
+retval=$?
+if [ $retval -ne 0 ] ;then
+ ERROR "$prog firewall - $retval see /tmp/I$$.log"
+ exit $retval
+fi
+
+echo "# Whonix firewall for wlan=$PROXY_WLAN LIBVIRT_FW=$LIBVIRT_FW" >> $OUT4
+
+if [ `id -u` -eq 0 ] && ls /etc/sysctl.d/*.conf 2>/dev/null >/dev/null; then
+ # hardcore
+ sed -i \
+ -e 's/forward = 0/forward = 1 ##libvirt/' \
+ -e 's/forwarding = 0/forwarding = 1 ##libvirt/' \
+ /etc/sysctl.d/*.conf
+
+ grep -l forward /etc/sysctl.d/*f | xargs sysctl -p | grep forward >/dev/null
+fi
+
+# mv $OUT4 /etc/firewall.conf.new || { echo ERROR: ; exit 9 ; }
+INFO "OK Whonix firewall - mv $OUT4 /etc/firewall.conf.new"
+
+exit 0
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_host.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_host.bash
new file mode 100755
index 0000000..8124ec3
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_host.bash
@@ -0,0 +1,534 @@
+#!/bin/bash
+# -*- mode: sh; tab-width: 8; coding: utf-8-unix -*-
+
+. /usr/local/bin/usr_local_tput.bash || exit 2
+PREFIX=/usr/local
+ROLE=proxy
+DELAY=10
+prog=proxy_whonix_host
+
+PL=$PREFIX/bin/proxy_libvirt_lib.bash
+
+USAGE="config|from_tor|to_tor|start|status|test|refresh|update"
+
+[ -f /usr/local/etc/testforge/testforge.bash ] && \
+ . /usr/local/etc/testforge/testforge.bash
+[ $( id -u ) -eq 0 ] || { ERROR $prog should be run as root ; exit 1 ; }
+
+. /usr/local/sbin/proxy_whonix_lib.bash || \
+ { ERROR loading /usr/local/sbin/proxy_whonix_lib.bash ; exit 2; }
+. /usr/local/bin/proxy_ping_lib.bash || exit 3
+
+prog=proxy_whonix_host
+[ -z "$MODE" ] && MODE=`proxy_ping_mode`
+
+HTTP_PROXY_PORT=3128
+HTTP_PROXY_HOST=127.0.0.1
+HTTPS_PORT=9128
+HTTPS_HOST=127.0.0.1
+proxy_ping_get_socks
+[ -z "$SOCKS_HOST" ] || SOCKS_HOST=127.0.0.1
+[ -z "$SOCKS_PORT" ] || SOCKS_PORT=9050
+proxy_ping_get_https
+proxy_ping_get_http
+
+WD=$PWD
+
+NEEDED_DIRS=""
+# /usr/local/lib/helper-scripts
+# /usr/local/etc/ssl
+
+NEEDED_SCRIPTS="
+/usr/local/bin/proxy_get_if.bash
+/usr/local/bin/proxy_libvirt_hook_qemu.bash
+/usr/local/bin/proxy_ping_lib.bash
+/usr/local/bin/proxy_ping_test.bash
+/usr/local/etc/jnettop.conf
+/usr/local/lib/helper-scripts/tor_bootstrap_check.py
+/usr/local/lib/helper-scripts/tor_bootstrap_check.bsh
+/usr/local/etc/ssl/cacert-testforge.pem
+/usr/local/sbin/Whonix-Gateway.rc
+/usr/local/sbin/debian_cache_to_archives.bash
+/usr/local/sbin/debian_elts_to_uris.bash
+/usr/local/sbin/debian_uris_to_urls.bash
+/usr/local/sbin/proxy_libvirt_ga_test.bash
+/usr/local/sbin/proxy_whonix_gateway_tor.bash
+/usr/local/sbin/proxy_whonix_guest_gateway.bash
+/usr/local/sbin/proxy_whonix_host-firewall.bash
+/usr/local/sbin/proxy_whonix_host_lib.bash
+/usr/local/sbin/proxy_whonix_host.bash
+/usr/local/sbin/proxy_whonix_host_tor.bash
+/usr/local/sbin/root_nm_wireless.bash
+"
+
+proxy_install_package () {
+ for pkg in $* ; do
+ if [ -d /etc/apt ] ; then
+ [ "$pkg" = guestfish ] && pkg=libguestfs-tools
+ apt-get install -y $pkg || return $?
+ elif [ -d /etc/portage ] ; then
+ apt-get install -y $pkg || return $?
+ fi
+ done
+ return 0
+}
+
+## proxy_whonix_host_dmesg_blocks
+proxy_whonix_host_dmesg_blocks () {
+ local retval=0
+
+ [ -f /etc/firewall.conf.block ] || touch /etc/firewall.conf.block
+ [ -z "$PROXY_WLAN" ] && PROXY_WLAN=`proxy_get_if` && retval=$?
+ [ $retval -ne 0 -o -z "$PROXY_WLAN" ] && {
+ ERROR $prog null interface && return 1
+ }
+ dmesg|tail -1000 | grep IPTABLES_FWI_REJECT-o| \
+ sed -e 's/.*SRC=//' -e 's/ .*//'|sort -u| \
+ while read elt ; do
+ grep -q $elt /etc/firewall.conf.block && continue
+ grep -q $elt /etc/firewall.conf && continue
+ echo $elt >> /etc/firewall.conf.block
+ done
+ [ -s /etc/firewall.conf.block ] || proxy_whonix_host_prepare_blocks || return 1$?
+ proxy_whonix_host_add_block $( cat /etc/firewall.conf.block ) || return 2$?
+
+ if [ ! -f /etc/firewall.conf.$$ -o ! -f /etc/firewall.conf ] ; then
+ return 3
+ elif diff /etc/firewall.conf.$$ /etc/firewall.conf ; then
+ return 4
+ else
+ base_wall.bash WARN: $prog BLOCKING \
+ $(diff /etc/firewall.conf.$$ /etc/firewall.conf | grep -v , | cut -f 7 -d ' ') \
+ in /etc/firewall.conf.block
+ proxy_ping_wlan_config /etc/firewall.conf.$$
+ mv /etc/firewall.conf /etc/firewall.conf.bak && \
+ mv /etc/firewall.conf.$$ /etc/firewall.conf && \
+ /usr/local/bin/proxy_libvirt_hook_network.bash
+ fi
+ return 0
+}
+
+## proxy_whonix_host_refresh
+proxy_whonix_host_refresh () {
+ local dire
+ [ "$#" -gt 0 ] && dire=$1
+ [ -z "$dire" ] && dire=$( proxy_ping_mode )
+ if [ $dire = whonix ] ; then
+ $PL proxy_libvirt_clean_iptables
+ proxy_whonix_host_dmesg_blocks
+ fi
+ return 0
+}
+
+## proxy_whonix_host_update
+proxy_whonix_host_update () {
+ local copy_in
+
+ # use nbd instead
+ return 0
+
+ DOM=$( proxy_whonix_get_gateway_dom )
+ [ -z "$DOM" ] && \
+ WARN proxy_whonix_host_update empty DOM from proxy_whonix_get_gateway_dom && \
+ DOM=Whonix-Gateway
+ cd /usr/local/sbin/
+
+ cp -p $PWD/$DOM.rc rc.local
+ copy_in="copy-in $PWD/rc.local /etc"
+ for dir in $NEEDED_DIRS ; do
+ copy_in="$copy_in
+mkdir $dir
+"
+ done
+ for file in $NEEDED_SCRIPTS ; do
+ dir=$( dirname $file )
+ copy_in="$copy_in
+copy-in $file $dir
+"
+ done
+
+ QCOW=/var/lib/libvirt/images/$DOM.qcow2
+ if [ -f $QCOW ] ; then
+ which virsh 2>/dev/null >/dev/null || proxy_install_package libvirt
+ proxy_virsh list | grep -q $DOM && virsh shutdown $DOM && echo sleep 60 && sleep 60
+ which guestfish 2>/dev/null >/dev/null || proxy_install_package guestfish
+ INFO copying in $( echo $NEEDED_SCRIPTS| wc -w ) files
+ guestfish -a $QCOW << EOF
+run
+mount /dev/sda1 /
+$copy_in
+umount /
+EOF
+ fi
+ rm -f rc.local
+
+ return 0
+}
+
+## proxy_whonix_host_config
+proxy_whonix_host_config () {
+ local dire
+ local retval=0
+ [ "$#" -gt 0 ] && dire=$1
+ [ -z "$dire" ] && dire=$( proxy_ping_mode )
+ DBUG proxy_whonix_host_config dire=$dire
+
+ [ -z "$PROXY_WLAN" ] && PROXY_WLAN=`proxy_get_if` && retval=$?
+ [ $retval -ne 0 -o -z "$PROXY_WLAN" ] && {
+ ERROR proxy_whonix_host_config null interface && return 1
+ }
+
+ proxy_ping_firewall_restart
+ proxy_ping_firewall_check || {
+ ERROR /etc/firewall.conf missing $? ; return 2 ;
+ }
+
+ proxy_ping_test_resolv $dire || return 4$?
+
+ proxy_whonix_privoxy_config $dire
+ proxy_ping_dnsmasq_config $dire || return 3$?
+
+ if [ -f /etc/inittab ] ; then
+ grep -q '^x1' /etc/inittab || \
+ sed -e 's/^x1/#x1/' -i /etc/inittab
+ # x1:12345:respawn:/sbin/agetty
+ fi
+
+ proxy_ping_firewall_modules
+ if [ "$dire" = whonix ] ; then
+ [ -f /var/lib/libvirt/images/Whonix-Gateway.qcow2 ] || \
+ WARN /var/lib/libvirt/images/Whonix-Gateway.qcow2 - mount /mnt/linuxKick150154
+
+ if [ -s /etc/firewall.conf.$dire ] ; then
+ proxy_ping_wlan_config /etc/firewall.conf.$dire /etc/firewall.conf
+ if ! diff -q /etc/firewall.conf.$dire /etc/firewall.conf ; then
+ cp -p /etc/firewall.conf.$dire /etc/firewall.conf
+ proxy_iptables_restore /etc/firewall.conf || return 3
+ fi
+ elif [ -s /etc/firewall.conf ] ; then
+ iptables-save |grep -q virbr1 || {
+ proxy_iptables_restore /etc/firewall.conf || return 4
+ }
+ else
+ [ -s /etc/firewall.conf.new ] || \
+ /usr/local/sbin/privacy_whonix_host-firewall.bash || \
+ { ERROR " $prog privacy_whonix_host-firewall.bash failed " ; return 5 ; }
+ [ -s /etc/firewall.conf.new ] || \
+ { ERROR " /etc/firewall.conf.new missing " ; return 6 ; }
+ [ -s /etc/firewall.conf ] || cp -p /etc/firewall.conf.new /etc/firewall.conf
+ proxy_iptables_restore < /etc/firewall.conf || return 7
+ fi
+
+ proxy_host_whonix_config $dire
+
+ elif [ "$dire" = selektor -o "$dire" = tor ] ; then
+ proxy_host_selektor_config $dire
+ fi
+
+
+ return 0
+}
+
+proxy_host_selektor_config () { DBUG proxy_host_selektor_config ;
+ local dire=$1
+
+ # /var/lib/tor/.SelekTOR/3xx/SelekTOR.xml
+ if [ -s /etc/firewall.conf.$dire ] ; then
+ proxy_ping_wlan_config /etc/firewall.conf.$dire /etc/firewall.conf
+ if ! diff -q /etc/firewall.conf.$dire /etc/firewall.conf ; then
+ cp -p /etc/firewall.conf.$dire /etc/firewall.conf
+ proxy_iptables_restore /etc/firewall.conf || return 8
+ elif [ -s /etc/firewall.conf ] ; then
+ iptables-save |grep -q gid-owner || \
+ proxy_iptables_restore /etc/firewall.conf || return 9
+ else
+ { ERROR " /etc/firewall.conf.$dire missing " ; return 7 ; }
+ fi
+ fi
+
+ return 0
+}
+
+## proxy_whonix_host_install
+proxy_whonix_host_install () { DBUG proxy_whonix_host_install $* ;
+
+ if [ $dire = host ] ; then
+ ERROR proxy_whonix_host_install host
+ return 1
+ elif [ $dire = whonix ] ; then
+ proxy_whonix_libvirt_start
+ proxy_whonix_gateway_start $dire
+ else
+ if /etc/init.d/libvirtd status ; then
+ proxy_virsh list | grep -q Whonix-Gateway && \
+ proxy_virsh shutdown Whonix-Gateway
+ fi
+ fi
+
+ /usr/local/sbin/proxy_whonix_host_tor.bash $dire || return 7$?
+
+ return 0
+}
+
+## proxy_host_from_config
+proxy_host_from_config () {
+ #? rm -f /etc/modules_load.d/vda*conf
+
+ DOM=$( proxy_whonix_get_gateway_dom )
+ [ -z "$DOM" ] && \
+ WARN proxy_host_whonix_config empty DOM assuming Whonix-Gateway && \
+ DOM=Whonix-Gateway
+
+ if [ -d /etc/libvirt/qemu/ -a /etc/libvirt/qemu/$DOM.xml ] ; then
+ if [ ! -f /etc/libvirt/qemu/$DOM.xml.dst ] ; then
+ cd /etc/libvirt/qemu/
+ cp -p /etc/libvirt/qemu/$DOM.xml /etc/libvirt/qemu/$DOM.xml.dst
+ for file in $WD/$DOM.xml.?.diff ; do
+ [ -f /etc/libvirt/qemu/$DOM.xml ] || \
+ ERROR $prog /etc/libvirt/qemu/$DOM.xml missing ; return 2
+ patch /etc/libvirt/qemu/$DOM.xml < $file
+ done
+ cd $WD
+ fi
+ fi
+ return 0
+}
+## proxy_host_from_config
+proxy_host_whonix_config () {
+ local dire=whonix
+ local file
+
+ [ -x /usr/local/bin/proxy_libvirt_hook_network.bash ] || return 1
+
+ if false && ! [ -x /etc/libvirt/hooks/network ] ; then
+ cat > /etc/libvirt/hooks/network < /dev/null || return 6
+ $0 -h > /dev/null || return 7
+ for elt in $( echo $USAGE | sed -e 's/|/ /g' ) ; do
+ grep -q ^proxy_whonix_host_$elt $0 || { WARN proxy_whonix_host_$elt NOT in $0 ; return 8 ; }
+ done
+
+ return 0
+}
+
+## proxy_whonix_host_status
+proxy_whonix_host_status () { proxy_whonix_host_test "$@" ; }
+
+## proxy_whonix_host_test
+proxy_whonix_host_test () {
+ local dire
+ [ "$#" -gt 0 ] && dire=$1
+ [ -z "$dire" ] && dire=$( proxy_ping_mode )
+
+ proxy_whonix_host_verify
+
+ proxy_ping_status
+
+ /usr/local/bin/proxy_ping_test.bash $dire || \
+ WARN $prog proxy_ping_test.bash FAILED $dire
+
+ if [ "$dire" = whonix ] ; then
+ grep "`date +%Y-%m-%d`.* error :" /var/local/log/libvirtd.log
+ proxy_whonix_host_tor.bash proxy_libvirt_test || return 1
+ proxy_virsh list | grep running || return 2
+
+ # FixMe look in /etc/libvirt/qemu
+ for elt in Whonix-Gateway Whonix-Workstation Pen19-1 Kick15-1 ; do
+ proxy_virsh list | grep -q $elt || continue
+ # /usr/local/sbin/proxy_libvirt_ga_test.bash $elt /bin/netstat -lnp4 ||
+ /usr/local/sbin/proxy_libvirt_ga_test.bash $elt ls /dev/virtio-ports/ || \
+ WARN $prog $elt not responding
+ # fallsover with
+ # error: internal error: unable to execute QEMU agent command 'guest-exec-status': Invalid parameter 'pid'
+ done
+ fi
+
+ return 0
+}
+
+## proxy_whonix_host_restart
+proxy_whonix_host_restart () {
+ local dire
+ [ "$#" -gt 0 ] && dire=$1 || dire=$MODE
+
+ proxy_whonix_host_start $dire || return 1$?
+ proxy_whonix_host_status $dire || return 2$?
+ return 0
+}
+
+## proxy_whonix_host_selektor
+proxy_whonix_host_selektor () {
+ local dire=selektor
+ proxy_whonix_host_start $dire
+ return $?
+}
+
+## proxy_whonix_host_from_tor
+proxy_whonix_host_from_tor () {
+ local dire=whonix
+ proxy_whonix_host_start $dire
+ return $?
+}
+
+## proxy_whonix_host_to_tor
+proxy_whonix_host_to_tor () {
+ local dire=tor
+ proxy_virsh list | grep -q Whonix-Gateway && proxy_virsh shutdown Whonix-Gateway
+ proxy_whonix_host_start $dire
+ return $?
+}
+
+## proxy_whonix_stop
+proxy_whonix_stop () {
+ local dire
+ [ "$#" -gt 0 ] && dire=$1
+ [ -z "$dire" ] && dire=$( proxy_ping_mode )
+ DBUG proxy_whonix_stop $*
+
+ if [ $dire = whonix -o $dire = host -o $dire = tor ] ; then
+ proxy_whonix_host_stop $dire
+ fi
+ return 0
+}
+
+## proxy_whonix_libvirt_stop
+proxy_whonix_libvirt_stop () {
+
+ proxy_virsh net-list | grep -q Whonix-External && \
+ virsh net-destroy Whonix-External
+
+ proxy_virsh net-list | grep -q Whonix-Internal && \
+ virsh net-destroy Whonix-Internal
+
+ proxy_virsh list | grep -q Whonix-Gateway && \
+ virsh shutdown Whonix-Gateway
+
+ proxy_virsh list | grep -q Whonix-Gateway && \
+ virsh destroy Whonix-Gateway
+
+ return 0
+}
+
+## proxy_whonix_host_stop
+proxy_whonix_host_stop () {
+ local dire=$1
+
+ DBUG $prog proxy_whonix_host_stop $*
+
+ if [ $dire = whonix ] ; then
+ proxy_rc_service polipo status >/dev/null && proxy_rc_service polipo stop
+ proxy_ping_dnsmasq_status && proxy_ping_dnsmasq_stop
+ proxy_whonix_libvirt_stop || return 3$?
+ elif [ $dire = tor ] ; then
+ proxy_rc_service tor status >/dev/null && proxy_rc_service tor stop
+ proxy_rc_service polipo status >/dev/null && proxy_rc_service polipo stop
+ fi
+
+
+ return 0
+}
+
+## proxy_whonix_gateway_start - start whonix on a host
+proxy_whonix_gateway_start () {
+ local dire
+ [ "$#" -gt 0 ] && dire=$1
+
+ # proxy_ping_dnsmasq_status && proxy_ping_dnsmasq_stop
+ proxy_whonix_libvirt_start || return 3$?
+
+ proxy_virsh net-list | grep -q Whonix-External || \
+ virsh net-start Whonix-External || return 4$?
+ ifconfig virbr1 || return 5$?
+
+ proxy_virsh net-list | grep -q Whonix-Internal || \
+ virsh net-start Whonix-Internal|| return 6$?
+ ifconfig virbr2 || return 7$?
+
+ DOM=$( proxy_whonix_get_gateway_dom )
+ [ -z "$GATEW_DOM" ] && \
+ WARN $prog empty DOM from proxy_whonix_get_gateway_dom && \
+ DOM=Whonix-Gateway
+ proxy_virsh list | grep -q $DOM || \
+ { INFO $prog virsh starting $DOM ; virsh start $DOM ; } || \
+ return 8$?
+
+ return 0
+}
+
+## proxy_whonix_host_start - start either whonix or tor on a host
+proxy_whonix_host_start () { DBUG $prog proxy_whonix_host_start $* ;
+ local dire
+ [ "$#" -gt 0 ] && dire=$1
+
+ proxy_whonix_host_config $dire || return 2$?
+
+ proxy_whonix_host_install $dire || return 4$?
+ proxy_clobber_resolv_local
+
+ return 0
+}
+
+if [ "$#" -eq 0 ] ; then
+ echo USAGE: $prog $USAGE
+
+ elif [ "$1" = '-h' -o "$1" = '--help' -o "$1" = 'host' ] ; then
+ echo USAGE: $prog $USAGE or:
+ grep '^## ' $0 | sed -e 's/^## //'
+
+ elif [ "$1" = config ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_config $MODE || exit 2$?
+
+ elif [ "$1" = start ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_start $MODE || exit 2$?
+
+ elif [ "$1" = selektor ] ; then
+ MODE=$1
+ proxy_whonix_host_start $MODE
+
+ elif [ "$1" = to -o "$1" = 'to_tor' -o "$1" = 'tor' ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_to_tor || exit 3$?
+
+ elif [ "$1" = from -o "$1" = 'from_tor' -o "$1" = 'whonix' ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_from_tor || exit 4$?
+
+ elif [ "$1" = verify -o "$1" = 'install' ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_$1 $MODE || exit 5$?
+
+ elif [ "$1" = 'test' ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_test $MODE || exit 4$?
+
+ elif [ "$1" = update -o "$1" = 'start' -o "$1" = 'status' -o "$1" = 'stop' ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_$1 $MODE || exit 5$?
+
+ elif [ "$1" = hourly -o "$1" = 'refresh' ] ; then
+ [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
+ proxy_whonix_host_refresh || exit 6$?
+
+ else
+ DBUG $base "$@"
+ eval "$@"
+ exit $?
+
+ fi
+
+exit 0
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_host_libvirt.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_host_libvirt.bash
new file mode 100755
index 0000000..47f893f
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_host_libvirt.bash
@@ -0,0 +1,3 @@
+#!/bin/bash
+# -*- mode: sh; tab-width: 8; coding: utf-8-unix -*-
+exec bash /usr/local/bin/proxy_ping_lib.bash proxy_libvirt_test "$@"
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_host_tor.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_host_tor.bash
new file mode 100755
index 0000000..5120c26
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_host_tor.bash
@@ -0,0 +1,257 @@
+#!/bin/bash
+# -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*-
+
+ROLE=proxy
+prog=$( basename $0 .bash )
+
+. /usr/local/bin/usr_local_tput.bash || exit 2
+PREFIX=/usr/local
+
+USAGE="[to_tor|from_tor|test_to|test_from|verify]"
+
+. /usr/local/sbin/proxy_whonix_lib.bash || \
+ { ERROR loading /usr/local/sbin/proxy_whonix_lib.bash ; exit 2; }
+. /usr/local/bin/usr_local_base.bash || exit 2
+. /usr/local/sbin/proxy_tor_lib.bash || \
+ { ERROR loading /usr/local/sbin/proxy_tor_lib.bash ; exit 3; }
+. /usr/local/bin/usr_local_base.bash || exit 2
+
+[ -f $PREFIX/etc/testforge/testforge.bash ] && . /usr/local/etc/testforge/testforge.bash
+[ -z "$PRIV_TOR_OWNER" ] && grep -q ^debian-tor /etc/passwd && PRIV_TOR_OWNER=debian-tor
+[ -z "$PRIV_TOR_OWNER" ] && grep -q ^tor /etc/passwd && PRIV_TOR_OWNER=tor
+PRIV_TOR_GID=$( grep ^$PRIV_TOR_OWNER /etc/passwd|cut -d: -f 4 )
+[ -z "$PRIV_BIN_OWNER" ] && PRIV_BIN_OWNER=bin
+PRIV_BIN_GID=$( grep ^$PRIV_BIN_OWNER /etc/passwd|cut -d: -f 4 )
+
+#ps ax | grep 'usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/network.conf' && \
+# ps ax | grep 'usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/network.conf' | sed -e 's/ .*//' \
+# | xargs kill
+
+[ $USER != root ] || proxy_iptables_save | grep -qi reject || \
+ proxy_ping_firewall_restart || exit 2$?
+# bash /usr/local/sbin/base_firewall_start.bash
+
+## proxy_whonix_or_tor
+proxy_whonix_or_tor () { DBUG proxy_whonix_or_tor $* ;
+ local a dire debian file
+ dire=$1
+ file=/etc/tor/torrc
+
+ [ -n "$PROXY_WLAN" ] || PROXY_WLAN=$( proxy_get_if ) || return 1$?
+ [ -n "$PROXY_WLAN" ] || return 2$?
+ DBUG proxy_whonix_to_tor PROXY_WLAN=$PROXY_WLAN $*
+
+ true || \
+ proxy_ping_online || {
+ wlan7=$PROXY_WLAN
+ base_wlan_modules_unload $PROXY_WLAN
+ proxy_base_wlan_modules_load $PROXY_WLAN
+ ERROR not online ret=$? ; return 3 ;
+ }
+ proxy_whonix_copy_files $dire
+## proxy_whonix_to_tor
+}
+
+proxy_whonix_to_selektor () { DBUG proxy_whonix_to_selektor $* ;
+ local a dire file
+ dire=selektor
+ file=
+ proxy_whonix_or_tor $dire
+ if ps ax | grep -v grep | grep -q 'tor -f /var/lib/tor/.SelekTOR/3xx' ; then
+ :
+ elif ! proxy_route_check ; then
+ return $?
+ elif tty >/dev/null ; then
+ /var/local/bin/selektor.bash &
+ fi
+
+}
+
+proxy_whonix_to_tor () { DBUG proxy_whonix_to_tor $* ;
+ local a dire debian file
+ dire=tor
+ file=/etc/tor/torrc
+
+ proxy_whonix_or_tor $dire || return 2$?
+ DBUG proxy_whonix_to_tor PROXY_WLAN=$PROXY_WLAN $*
+
+ proxy_tor_torrc_update /etc/tor/torrc 127.0.0.1
+ proxy_tor_torrc_exclude /etc/tor/torrc
+ # proxy_rc_service tor status >/dev/null || proxy_rc_service tor start
+ # weaker - includes running from cmdline
+ debian=$PRIV_TOR_OWNER
+ ps ax -g $debian | grep -v grep | grep -q ' tor ' || \
+ proxy_rc_service tor start || \
+ { ERROR not service start ret=$? ; return 3 ; }
+
+
+ proxy_whonix_privoxy_start tor || {
+ echo WARN: $prog privoxy NOT running ret=$?
+ # return 4 ;
+ }
+
+ proxy_whonix_dnsmasq_start tor || {
+ echo WARN: proxy_whonix_to_tor dnsmasq NOT started retval=$?
+ # return 5$? ;
+ }
+
+ # proxy_whonix_start_wget
+
+ proxy_iptables_save | grep -q 'udp --dport 53 -j DNAT --to-destination 127.0.0.1:9053' || \
+ proxy_rc_service dnsmasq status >/dev/null || \
+ { ERROR $prog dnsmasq not running ; return 6 ; }
+
+ netstat -nlp4 | grep 127.0.0.1:9 || return 9
+ return 0
+}
+
+## proxy_tor_clean
+proxy_tor_clean () {
+ [ -n "$MODE" ] || MODE="$( proxy_ping_mode )"
+ if [ "$MODE" = whonix ] ; then
+ proxy_whonix_get_gateway_dom || exit 8
+ if [ -z "$GATEW_DOM" ] ; then
+ proxy_virsh list | grep -q $GATEW_DOM && \
+ proxy_libvirt_clean_virbr1_rules
+ fi
+ fi
+ return 0
+}
+
+## proxy_tor_test
+proxy_tor_test () {
+ local dire
+ [ $# -eq 1 ] && dire=$1
+ [ -z "$dire" ] && dire="$( proxy_ping_mode )"
+
+ if [ $dire = tor -o $dire = whonix -o $dire = host ] ; then
+ # is vda a host?
+ proxy_tor_test_ntp || return 2$?
+ proxy_tor_test_anondate # || return 3$?
+ fi
+
+ proxy_whonix_test $dire || return 1$?
+
+ return 0
+}
+
+starbucks_torrc () { proxy_whonix_host_tor_install $* ; }
+## proxy_whonix_host_install
+proxy_whonix_host_tor_install () { DBUG proxy_whonix_host_tor_install $* ;
+ [ -n "$PROXY_WLAN" ] || PROXY_WLAN=$( proxy_get_if ) || return 1$?
+ [ -n "$PROXY_WLAN_IP" ] || PROXY_WLAN_IP=$( proxy_get_wlan_ip ) || \
+ { ERROR proxy_whonix_host_tor_install ifconfig $PROXY_WLAN ; return 7 ; }
+ [ -z "$PROXY_WLAN_IP" ] && return 0
+
+ for file in /etc/tor/torrc /etc/tor/torrc-defaults ; do
+ [ -f $file ] || continue
+ grep -q "SocksPolicy accept " /etc/tor/torrc || continue
+ grep -q "SocksPolicy accept $PROXY_WLAN_IP" /etc/tor/torrc || continue
+ sed -e "s@^SocksPolicy accept [^/]*\$@SocksPolicy accept $PROXY_WLAN_IP@" \
+ -i $file
+ done
+
+ return 0
+}
+
+proxy_whonix_host_whonix () { proxy_whonix_from_tor $* ; }
+## proxy_whonix_from_tor
+proxy_whonix_from_tor () {
+ local dire=whonix
+ local ret
+ DBUG proxy_whonix_from_tor $*
+
+ proxy_rc_service tor status >/dev/null && proxy_rc_service tor stop
+
+ [ -n "$PROXY_WLAN" ] || PROXY_WLAN=$( proxy_get_if ) || return 1$?
+ # ; return 2$ret
+ proxy_whonix_config $dire || { ret=$? ; ERROR proxy_whonix_from_tor failed proxy_whonix_config ret=$ret ; return 2$ret ; }
+
+ proxy_whonix_libvirt_start || {
+ ret=$? ;
+ ERROR proxy_whonix_from_tor failed proxy_whonix_libvirt_start ret=$ret ;
+ return 3$ret
+ }
+
+ a=$( proxy_iptables_save | grep -e '-A OUTPUT -o .* -m tcp -p tcp -m owner --gid-owner $PRIV_TOR_GID -j ACCEPT' | grep -c -v grep )
+ [ $? -eq 0 ] && [ -n "$a" ] && [ "$a" -gt 0 ] && \
+ WARN proxy_iptables -D OUTPUT -o $PROXY_WLAN -m tcp -p tcp -m owner --gid-owner $PRIV_TOR_GID -j ACCEPT
+
+ proxy_whonix_copy_files $dire
+
+ # netstat -nlp4e | grep 127.0.0.1:53 && { ERROR dns still running ; return 3;}
+ if false; then
+ proxy_rc_service pdnsd status >/dev/null && proxy_rc_service pdnsd stop
+ [ -f /etc/pdnsd/pdnsd.conf.whonix ] && \
+ cp -p /etc/pdnsd/pdnsd.conf.whonix /etc/pdnsd/pdnsd.conf
+
+ # proxy_whonix_start_wget
+ proxy_whonix_dnsmasq_start $dire || \
+ { ret=$? ; echo WARN: proxy_whonix_from_tor dnsmasq NOT started $ret ; }
+ fi
+
+ proxy_whonix_privoxy_start $dire || \
+ { ret=$?; echo WARN: proxy_privoxy_from_tor polipo not started $ret ; }
+
+ proxy_whonix_host_tor_install
+
+ return 0
+}
+
+if [ "$#" -eq 0 ] ; then
+ echo USAGE: $prog $USAGE
+
+ elif [ "$1" = '-h' ] || [ "$1" = 'help' ] || [ "$1" = '--help' ] ; then
+ echo USAGE: $prog $USAGE or:
+ grep '^## ' $0 | sed -e 's/^## //'
+
+ elif [ "$1" = to -o "$1" = 'to_tor' -o "$1" = 'tor' ] ; then
+ [ $( id -u ) -eq 0 ] || { ERROR $prog must be root ; exit 1 ; }
+ proxy_whonix_to_tor || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 1$ret ; }
+
+ elif [ "$1" = 'selektor' ] ; then
+ [ $( id -u ) -eq 0 ] || { ERROR $prog must be root ; exit 1 ; }
+ proxy_whonix_to_selektor || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 1$ret ; }
+
+ elif [ "$1" = 'from' -o "$1" = 'from_tor' -o "$1" = 'whonix' ] ; then
+ [ $( id -u ) -eq 0 ] || { ERROR $prog must be root ; exit 1 ; }
+ proxy_whonix_from_tor || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 2$ret ; }
+
+ elif [ "$1" = 'gateway' ] ; then
+ [ $( id -u ) -eq 0 ] || { ERROR $prog must be root ; exit 1 ; }
+ proxy_whonix_gateway || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 2$ret ; }
+ proxy_whonix_test gateway || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 4$ret ; }
+
+ elif [ "$1" = 'test_from' -o "$1" = 'test_whonix' ] ; then
+ [ $( id -u ) -eq 0 ] || { ERROR $prog must be root ; exit 1 ; }
+ proxy_tor_test whonix || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 6$ret ; }
+ /usr/local/bin/proxy_ping_test.bash panic || exit 7
+
+ elif [ "$1" = 'test_gateway' -o "$1" = 'test_gateway' ] ; then
+ proxy_tor_test gateway || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 6$ret ; }
+ /usr/local/bin/proxy_ping_test.bash panic || exit 7
+
+ elif [ "$1" = 'test_to' -o "$1" = 'test_tor' ] ; then
+ proxy_tor_test tor || { ret=$? ; ERROR $prog $prog $1 retval=$ret ; exit 7$ret ; }
+ /usr/local/bin/proxy_ping_test.bash panic || exit 7
+
+ elif [ "$1" = 'direct' -o "$1" = 'test_direct' ] ; then
+ /usr/local/bin/proxy_ping_test.bash direct
+
+ elif [ "$1" = 'verify' ] ; then
+ /usr/local/bin/proxy_ping_test.bash panic || exit 7
+ [ -n "$MODE" ] || MODE="$( proxy_ping_mode )"
+ proxy_whonix_test $MODE || \
+ { ret=$? ; ERROR "$prog host='$GATEW_DOM' retval=$ret" ; exit 8$ret ; }
+
+ elif [ "$1" = 'clean' -o "$1" = 'stop' ] ; then
+ proxy_whonix_$1
+ /usr/local/bin/proxy_ping_test.bash panic || exit 8
+
+ elif [ "$1" = 'config' ] ; then
+ ERROR $prog not implemented $1;exit 1
+
+ else
+ eval "$@"
+ exit $?
+ fi
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_lib.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_lib.bash
new file mode 100755
index 0000000..59026a9
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_lib.bash
@@ -0,0 +1,742 @@
+#!/bin/bash
+# -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*-
+
+PREFIX=/usr/local
+ROLE=proxy
+prog=$( basename $0 .bash )
+export PATH=$PATH:$PREFIX/sbin:$PREFIX/bin
+. $PREFIX/bin/usr_local_tput.bash
+
+PL=$PREFIX/bin/proxy_libvirt_lib.bash
+
+# . $PREFIX/sbin/proxy_whonix_lib.bash || { echo ERROR: loading $PREFIX/sbin/proxy_whonix_lib.bash ; exit 2; }
+. $PREFIX/bin/proxy_ping_lib.bash || \
+ { echo ERROR: loading $PREFIX/bin/proxy_ping_lib.bash ; exit 2; }
+base=proxy_whonix_lib
+
+starbucks_torrc () {
+ ip=`ifconfig $wlan7 | grep -v '127.0.0.1\|grep' | grep inet.*broadcast| sed -e 's/.*inet //' -e 's/ .*//'`
+ [ $? -eq 0 ] || { echo ERROR: starbucks_torrc ifconfig $wlan7 ; return 7 ; }
+ [ -z "$ip" ] && return 0
+ for file in /etc/tor/torrc /etc/tor/torrc-default ; do
+ grep -q "^SocksPolicy accept " /etc/tor/torrc || continue
+ grep -q "^SocksPolicy accept $ip$" /etc/tor/torrc && continue
+ sed -e "s@^SocksPolicy accept [^/]*\$@SocksPolicy accept $ip@" \
+ -i $file
+ done
+ return
+}
+
+starbucks_set () {
+
+ if [ -f /etc/init.d/network-manager ] ; then
+ NetworkManager=network-manager
+ elif [ -f /etc/init.d/NetworkManager ] ; then
+ NetworkManager=NetworkManager
+ elif [ -f /lib/systemd/system/NetworkManager ] ; then
+ NetworkManager=NetworkManager
+ else
+ NetworkManager=network-manager
+ fi
+ mgr=$NetworkManager
+ mgr=wicd
+
+ [ -x /mnt/linuxBack52/usr/bin/macchanger ] && \
+ macchanger=/mnt/linuxBack52/usr/bin/macchanger || \
+ macchanger=macchanger
+
+ # may be empty wlan7
+ # ifconfig wlan7 2>/dev/null && wlan7=wlan7 || wlan7=wlp3s0
+ if [ -z "$wlan7" ] ; then
+ echo ERROR: null wlan7 ;exit 1
+ fi
+ INFO starbucks_set wlan7=$wlan7 mgr=$mgr macchanger=$macchanger
+
+ if [ -z "$wlan7" ] ; then
+ rmmod iwlmvm iwlwifi 2>/dev/null >/dev/null &
+ rmmod ath9k_htc ath9k_common ath9k_hw ath 2>/dev/null >/dev/null &
+
+ elif [ $wlan7 = wlan4 ] ; then
+ rmmod iwlmvm iwlwifi 2>/dev/null >/dev/null &
+ elif [ $wlan7 = wlan6 -o $wlan7 = wlan7 ] ; then
+ rmmod ath9k_htc ath9k_common ath9k_hw ath 2>/dev/null >/dev/null &
+ fi
+ sleep 5
+
+ return 0
+}
+
+starbucks_ip () {
+ local wlan7
+ [ $# -eq 0 -o -z "$1" ] && return 1
+ wlan7=$1
+ base_wlan_modules_unload $wlan7 || return 1$?
+ base_wlan_modules_load $wlan7 || return 2$?
+
+ cd /etc
+ grep -l 'wlan[0-9]' * */* 2>/dev/null|grep -v ~$|xargs sed -e "s/wlan[0-9]/$wlan7/g" -i
+
+ local_rc_service dbus start;local_rc_service wicd start
+ return 0
+}
+
+starbucks_start_services () {
+ [ -z "$MODE" ] && echo ERROR: $0 unknown MODE && return 2
+ $PREFIX/sbin/proxy_whonix_host.bash start || return 3$?
+ # $PREFIX/sbin/proxy_whonix_host.bash proxy_whonix_host_start $MODE || return 5$?
+ [ "$MODE" != tor ] || starbucks_torrc || return 5$?
+ return 0
+}
+
+starbucks_stop () {
+ [ "$#" -eq 0 ] && set -- stop
+ starbucks_restart stop
+}
+
+# old tor only
+starbucks_restart () {
+ [ "$#" -eq 0 ] && set -- start
+ if [ -x /bin/systemctl ] ; then
+# [ -e /etc/tor/torrc ] && /bin/systemctl $1 tor >/dev/null
+ [ -e /etc/pdnsd.conf ] && /bin/systemctl $1 pdnsd >/dev/null
+ [ -e /etc/polipo.conf ] && /bin/systemctl $1 polipo >/dev/null
+ /bin/systemctl $1 $mgr
+ else
+# [ -e /etc/tor/torrc ] && /etc/init.d/tor $1
+ [ -e /etc/pdnsd.conf ] && /etc/init.d/pdnsd $1
+ [ -e /etc/polipo.conf ] && /etc/init.d/polipo $1
+ /etc/init.d/$mgr $1
+ fi
+ return 0
+}
+
+starbucks_pdnsd () {
+ if [ "$pdnsd" = "dnscrypt" ] && \
+ ! ps ax | grep -v grep | grep -q /dnscrypt-proxy ; then
+ cp /dev/null /var/local/var/log/dnscrypt-proxy.log
+ $HARDEN_VAR_LOCAL/bin/dnscrypt-proxy --config $HARDEN_VAR_LOCAL/etc/dnscrypt-proxy.toml &
+ sleep $DELAY
+ [ ! -s /var/local/var/log/dnscrypt-proxy.log ] || \
+ ! grep -q 'No servers configured' $HARDEN_VAR_LOCAL/var/log/dnscrypt-proxy.log || return 11
+ ps ax | grep -v grep | grep -q /dnscrypt-proxy || return 12
+ elif [ "$pdnsd" = "pdnsd" ] && ! ps ax | grep -v grep | grep -q /pdnsd ; then
+ if [ -x /bin/systemctl ] ; then
+ [ -e /etc/pdnsd.conf ] && /bin/systemctl stop pdnsd >/dev/null
+ else
+ [ -e /etc/pdnsd.conf ] && /etc/init.d/pdnsd stop
+ fi
+ fi
+}
+
+starbucks_torrc () {
+ ip=`ifconfig $wlan7 | grep -v '127.0.0.1\|grep' | grep inet.*broadcast| sed -e 's/.*inet //' -e 's/ .*//'`
+ [ $? -eq 0 ] || { echo ERROR: starbucks_torrc ifconfig $wlan7 ; return 7 ; }
+ [ -z "$ip" ] || \
+ grep -q "SocksPolicy accept $ip@" /etc/tor/torrc || \
+ sed -e "s@^SocksPolicy accept [^/]*\$@SocksPolicy accept $ip@" \
+ -i /etc/tor/torrc
+}
+
+
+## proxy_guest_firewall_config -- /etc/firewall.conf.ws.new
+proxy_guest_firewall_config () {
+ . $PREFIX/sbin/proxy_whonix_guest_workstation-firewall.bash || return 2$?
+ source_config_folder
+ iptables_cmd="echo iptables"
+ ip6tables_cmd="echo # ip6tables"
+ main > /etc/firewall.conf.ws.new
+
+ return $?
+}
+
+## proxy_whonix_guest_config
+proxy_whonix_guest_config () {
+ return 0
+}
+
+## proxy_whonix_guest_start
+proxy_whonix_guest_start () {
+ $PL proxy_libvirt_start_guest
+ return $?
+}
+
+## proxy_whonix_test_guest
+proxy_whonix_test_guest () {
+ $PL proxy_libvirt_test_guest
+ return $?
+}
+
+## proxy_whonix_gateway_config
+proxy_whonix_gateway_config () {
+ proxy_whonix_dnsmasq_config gateway 10.0.2.15
+ return 0
+}
+
+## proxy_whonix_dnsmasq_config
+proxy_whonix_dnsmasq_config () {
+ local dire
+
+ [ "$#" -eq 0 ] || dire=$1
+ [ -z "$dire" ] && MODE="$( proxy_ping_mode )" && dire=$MODE
+ [ -n "$MODE" ] || MODE=host
+
+ proxy_dest_port_wlan_config
+ [ -z "$PORT" -o -z "$DEST" ] && return 1
+
+ # 9040 - no wgetrc polipo
+ # need dnsmasq to 127
+ file=/etc/dnsmasq.conf
+ if [ ! -f $file.$dire ] ; then
+ cp -p $file $file.$dire
+ cat >> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.conf <> $file.$dire </dev/null || \
+ proxy_rc_service libvirtd start || \
+ echo WARN: libvirtd crashed - see /var/log/libvirt/libvirtd.log # 2>&1|tee $WLOG
+ $PL proxy_libvirt_status
+ return 0
+}
+
+## proxy_whonix_libvirt_start
+proxy_whonix_libvirt_start () {
+ local domain
+ [ "$#" -ge 1 ] && domain=$1
+
+ if [ ! -e /run/libvirt/libvirt-sock ] || ! proxy_rc_service libvirtd status >/dev/null ; then
+ cp /dev/null /var/log/libvirt/libvirtd.log
+ /etc/init.d/libvirtd status
+ retval=$?
+ [ $retval -eq 32 ] && WARN libvirtd crashed - zapping && /etc/init.d/libvirtd zap
+ [ $retval -eq 0 ] || /etc/init.d/libvirtd start || return 5$? # error: Failed to start livirtd
+ proxy_rc_service libvirtd start || return 3
+ sleep $DELAY
+ fi
+ $PL proxy_libvirt_no_autostart
+ $PL proxy_libvirt_start
+ $PL proxy_libvirt_status
+ proxy_virsh net-list | grep -q Whonix-Internal || virsh net-start Whonix-Internal || return 3
+ proxy_virsh net-list | grep -q Whonix-External || virsh net-start Whonix-External || return 4
+
+ [ -z "$domain" ] && domain="$( proxy_testforge_get_gateway_dom )"
+ [ -z "$domain" ] && echo WARN: null proxy_testforge_get_gateway_dom && \
+ domain=Whonix-Gateway && \
+ INFO set proxy_testforge_get_gateway_dom $domain
+ $PL proxy_libvirt_list | grep -v grep | grep "$domain" || \
+ virsh start $domain || {
+ ret=$?
+ echo ERROR: proxy_whonix_libvirt_start failed virsh start $domain ret=$ret
+ return 5$ret
+ }
+
+ return 0
+}
+
+## proxy_whonix_test
+proxy_whonix_test () {
+ local dire
+ DBUG proxy_whonix_test $dire
+ [ "$#" -eq 0 ] && dire=$MODE || dire=$1
+
+ [ $dire = ws -o $dire = workstation ] && dire=vda
+
+ if [ $dire = client ] ; then
+ :
+ # dunno - look at netstat? -nle4
+
+ elif [ $dire = nat ] ; then
+ $PL proxy_libvirt_test_guest
+
+ elif [ $dire = vda -o $dire = gateway ] ; then
+ proxy_whonix_test_guest
+
+ elif [ $dire = tor ] ; then
+ $PL proxy_libvirt_test_host
+
+ elif [ $dire = whonix ] ; then
+ $PL proxy_libvirt_no_autostart
+ $PL proxy_libvirt_clean_virbr1_rules
+
+ proxy_whonix_get_gateway_dom
+ [ -z "$GATEW_DOM" ] && echo WARN: $prog DOM proxy_whonix_get_gateway_dom assuming Whonix-Gateway && DOM=Whonix-Gateway || DOM=$GATEW_DOM
+
+ proxy_virsh list | grep -q $DOM || { echo ERROR: $prog $DOM not running ; return 2 ; }
+
+ $PREFIX/bin/proxy_ping_test.bash from_tor || return 6$?
+ fi
+
+ #? gateway
+ if [ $dire = whonix -o $dire = vda -o $dire = tor ] ; then
+ proxy_rc_service polipo status >/dev/null >/dev/null || \
+ { echo ERROR: $prog polipo not running ; return 4 ; }
+ $PREFIX/bin/proxy_ping_test.bash polipo || return 9$?
+ elif [ $dire = host -o $dire = tor ] ; then
+ proxy_rc_service privoxy status >/dev/null >/dev/null || \
+ { echo ERROR: $prog privoxy not running ; return 4 ; }
+ $PREFIX/bin/proxy_ping_test.bash privoxy || return 9$?
+ fi
+
+ if [ $dire = vda -o $dire = ws -o $dire = workstation ] ; then
+ proxy_clobber_resolv_local 10.152.152.10
+ elif [ $dire = gateway -o $dire = whonix -o $dire = tor ] ; then
+ proxy_rc_service dnsmasq status 2>/dev/null >/dev/null || \
+ { echo ERROR: $prog dnsmasq not running ; return 5 ; }
+ proxy_clobber_resolv_local 127.0.0.1
+ fi
+ $PREFIX/bin/proxy_ping_test.bash dns # || return 9$?
+
+ $PREFIX/bin/proxy_ping_test.bash $dire || return 6$?
+
+ return 0
+}
+
+# Weher was this
+## rc_host_symlink_etc_fstab
+rc_host_symlink_etc_fstab () {
+ grep -q root=/dev/vda /proc/cmdline
+ PROXY_IS_VDA=$?
+if [ $PROXY_IS_VDA -eq 0 ] ; then
+ [ -h /etc/fstab ] && [ -f /etc/fstab.vda ] && \
+ rm -f /etc/fstab && ln -s /etc/fstab.vda /etc/fstab
+ return 1
+# else
+# [ -h /etc/fstab ] && [ -f /etc/fstab.4TA ] && \
+# rm -f /etc/fstab && ln -s /etc/fstab.4TA /etc/fstab
+ fi
+
+ return 0
+}
+
+## proxy_vda_config
+proxy_vda_config () {
+
+ rc_host_symlink_etc_fstab
+ sed -e 's/^#x1/x1/' -i /etc/inittab #
+
+ if false ; then
+ sed -e 's/^#//' -i $PREFIX/etc/modules_load.d/vda*conf
+ if [ ! -h /etc/modules_load.d/vda_mods.conf ] ; then
+ ln -s $PREFIX/etc/modules_load.d/vda*conf /etc/modules_load.d/
+ fi
+ fi
+ if false ; then
+ [ -f /etc/firewall.conf.vda ] && \
+ cp -p /etc/firewall.conf.vda /etc/firewall.conf
+ fi
+ return 0
+}
+
+##
+old_proxy_vda_config () {
+
+ [ -f /etc/inittab ] && sed -e 's/^#x1/x1/' -i /etc/inittab
+
+ return 0
+}
+
+## proxy_vda_whonix_config
+proxy_vda_whonix_config () {
+ local dir=vda
+
+ DEST=10.152.152.10
+ PROXY_WLAN=eth0
+ proxy_host_whonix_config $dire $DEST 9053 $PROXY_WLAN
+
+ return $?
+}
+
+## proxy_quest_config
+proxy_quest_config () {
+
+ proxy_vda_config
+
+ sed -e 's/^#//' -i $PREFIX/etc/modules_load.d/vda*conf
+ if [ ! -h /etc/modules_load.d/vda_mods.conf ] ; then
+ cp -np $PREFIX/etc/modules_load.d/vda*conf /etc/modules-load.d/
+ fi
+ return 0
+}
+
+## proxy_whonix_dnsmasq_start
+proxy_whonix_dnsmasq_start () {
+ local dire
+ local service=dnsmasq
+
+ [ "$#" -eq 0 ] || dire=$1
+ [ -z "$dire" ] && MODE="$( proxy_ping_mode )" && dire=$MODE
+ [ -n "$MODE" ] || MODE=host
+
+ DBUG proxy_whonix_dnsmasq_start $dire $PROXY_WLAN
+
+ proxy_whonix_config $dire || return 1$?
+
+ PROXY_WLAN=$( proxy_get_if )
+ [ -z "$PROXY_WLAN" ] && echo ERROR: $prog empty PROXY_WLAN && return 4
+
+ sed -e "s/wlan[0-9]/$PROXY_WLAN/" -i /etc/dnsmasq.conf.$dire
+ if diff /etc/dnsmasq.conf.$dire /etc/dnsmasq.conf >/dev/null ; then
+ proxy_rc_service dnsmasq status >/dev/null || \
+ proxy_ping_dnsmasq_start || return 8$?
+ else
+ proxy_rc_service dnsmasq status >/dev/null && \
+ proxy_ping_dnsmasq_stop
+ cp -p /etc/dnsmasq.conf.$dire /etc/dnsmasq.conf
+ proxy_ping_dnsmasq_start || return 8$?
+ fi
+
+ return 0
+}
+
+## proxy_whonix_privoxy_start
+proxy_whonix_polipo_start () {
+ local dire
+ local service=polipo
+
+ [ $# -eq 1 ] && dire=$1
+ [ -z "$dire" ] && dire="$( proxy_ping_mode )"
+ DBUG proxy_whonix_start_$service $dire
+
+ proxy_whonix_config $dire || \
+ echo WARN: proxy_whonix_polipo_start proxy_whonix_config $dire $? # return 1$?
+
+ sed -e "s/wlan[0-9]/$PROXY_WLAN/" -e "s/eth[0-9]/$PROXY_WLAN/" -i /etc/polipo/config.$dire
+
+ if ! diff /etc/polipo/config.$dire /etc/polipo/config ; then
+ cp -p /etc/polipo/config.$dire /etc/polipo/config
+ proxy_rc_service $service restart || return 2$?
+ else
+ proxy_rc_service $service status >/dev/null || \
+ proxy_rc_service $service start||return 3$
+ fi
+
+ return 0
+}
+
+## proxy_whonix_host_prepare_blocks
+proxy_whonix_host_prepare_blocks () {
+ if [ ! -s /etc/firewall.conf.block ] ; then
+ if [ -f $PREFIX/etc/firewall.conf.block ] ; then
+ echo "WARN: $prog copying $PREFIX/etc/firewall.conf.block"
+ cp -p $PREFIX/etc/firewall.conf.block /etc/firewall.conf.block
+ else
+ ERROR "$prog missing $PREFIX/etc/firewall.conf.block"
+ return 1
+ fi
+ fi
+ return 0
+}
+
+## proxy_whonix_host_add_block
+proxy_whonix_host_add_block () {
+ local elt tab ip
+
+ # PROXY_WLAN=$( proxy_get_if )
+ # [ $? -ne 0 -o -z "$PROXY_WLAN" ] && echo ERROR: $prog null interface && return 1
+ if [ "$#" -eq 0 ] ; then
+ proxy_whonix_host_prepare_blocks \| return 1$?
+ set -- $( cat /etc/firewall.conf.block )
+ fi
+ # DBUG "$prog adding $*"
+ [ -f /etc/firewall.conf.newer ] || \
+ cp -p /etc/firewall.conf /etc/firewall.conf.newer
+ for elt in wlan virbr1 ; do
+ [ $elt = wlan ] && tab=INPUT || tab=LIBVIRT_FWI
+ grep -q "^# blocks $elt" /etc/firewall.conf.newer || {
+ echo ERROR: maker not found "^# blocks $elt" in /etc/firewall.conf.newer
+ return 2
+ }
+ sed -e "/^# blocks $elt/,\$d" /etc/firewall.conf.newer > /etc/firewall.conf.$$
+ echo "# blocks $elt" >> /etc/firewall.conf.$$
+ for ip in $* ; do
+ grep -q $ip /etc/firewall.conf.block || \
+ grep -q $ip /etc/firewall.conf.block.newer || \
+ echo $ip >> /etc/firewall.conf.block.newer
+ grep -q -e "A $tab -s $ip" /etc/firewall.conf.newer && continue
+ echo "-A $tab -s $ip -p tcp -j DROP" >> /etc/firewall.conf.$$
+ DBUG "$prog -A $tab -s $ip -m tcp -p tcp -j DROP"
+ done
+ sed -e "1,/^# blocks $elt/d" /etc/firewall.conf.newer >> /etc/firewall.conf.$$
+ mv /etc/firewall.conf.$$ /etc/firewall.conf.newer
+ done
+ return 0
+}
+
+## proxy_whonix_host_online
+proxy_whonix_host_online () {
+ [ -n "$PROXY_WLAN" ] || PROXY_WLAN=$( proxy_get_if ) || return 1$?
+ [ -z "$PROXY_WLAN" ] && echo ERROR: empty PROXY_WLAN && return 2
+ if [ -x /etc/init.d/NetworkManager ] ; then
+ /etc/init.d/NetworkManager status || /etc/init.d/NetworkManager start || return 3
+else
+ proxy_rc_service NetworkManager status >/dev/null \
+ || proxy_rc_service NetworkManager start || return 3$?
+fi
+ nm-online -t 0 -x || return 4$?
+
+ return 0
+}
+
+## proxy_whonix_down - call when the network goes down
+proxy_whonix_down () {
+# $PREFIX/bin/proxy_ping_test.bash "$MODE" || return 1$?
+ proxy_ping_online && return 0 # dont do anything
+ # nothing to do?
+ return 0
+}
+
+## proxy_whonix_up - call when the network comes up
+proxy_whonix_up () {
+ # $PREFIX/bin/proxy_ping_test.bash "$MODE" || return 1$?
+ proxy_ping_online || return 0 # dont do anything
+ return 0
+}
+
+## proxy_whonix_start_wget
+proxy_whonix_start_wget () {
+ return 0
+ if [ -f /etc/wgetrc ] ; then
+ sp=https://127.0.0.1:3128
+ grep -q ^https_proxy /etc/wgetrc && \
+ sed -e "s@https_proxy.*@https_proxy = $sp@" -i /etc/wgetrc
+ grep -q ^https_proxy /etc/wgetrc && \
+ echo "https_proxy = $sp" >> /etc/wgetrc
+ grep -q ^http_proxy /etc/wgetrc && \
+ sed -e "s@http_proxy.*@http_proxy = $sp@" -i /etc/wgetrc
+ grep -q ^http_proxy /etc/wgetrc || \
+ echo "http_proxy = $sp" >> /etc/wgetrc
+ fi
+
+ sp=http://127.0.0.1:3128
+ for elt_proxy in http https ; do
+ grep -q ^$elt_proxy /etc/wgetrc && \
+ sed -e "s@$elt_proxy.*@$elt_proxy = $sp@" -i /etc/wgetrc || \
+ echo "$elt_proxy = $sp" >> /etc/wgetrc
+ done
+
+ return 0
+}
+
+if [ -x /usr/bin/basename ] && [ $( /usr/bin/basename -- $0 .bash ) = $base ] ; then
+ [ "$#" -eq 0 ] && exit 0
+ [ "$#" -eq 1 ] && [ "$1" = '-h' -o "$1" = '--help' ] && \
+ echo USAGE: $0 && grep '^[a-z].*()\|^## ' $0 | sed -e 's/().*//'|sort && \
+ exit 0
+ DBUG $base "$@"
+ eval "$@"
+ exit $?
+ fi
diff --git a/overlay/Linux/usr/local/sbin/proxy_whonix_tor_start.bash b/overlay/Linux/usr/local/sbin/proxy_whonix_tor_start.bash
new file mode 100755
index 0000000..54f5ecb
--- /dev/null
+++ b/overlay/Linux/usr/local/sbin/proxy_whonix_tor_start.bash
@@ -0,0 +1,2 @@
+#!/bin/bash
+exec sh proxy_whonix_gateway_tor.bash "$@"
diff --git a/overlay/Linux/usr/local/share/doc/txt/gitconfig3.txt b/overlay/Linux/usr/local/share/doc/txt/gitconfig3.txt
new file mode 100644
index 0000000..f8ec4a2
--- /dev/null
+++ b/overlay/Linux/usr/local/share/doc/txt/gitconfig3.txt
@@ -0,0 +1,93 @@
+# -*-mode: doctest; tab-width: 0; py-indent-offset: 4; coding: utf-8-unix -*-
+
+== testserver box testing ==
+
+ >>> import os # doctest: +REPORT_ONLY_FIRST_FAILURE
+
+This is a Python doctest file that is executable documentation.
+It is built to run in the host against a Vagranted VirtualBox, and is run
+from the directory that contains the box's {{{.vagrant}}} subdirectory.
+
+ >>> import subprocess
+ >>> import sys
+ >>> import time
+
+And, now run tests against the box.
+
+ >>> sys.stderr.write("Running tests against box" +'\n')
+ 26
+
+=== Box settings ===
+
+We'll need the settings defined in {{{/usr/local/etc/testforge/testforge.yml}}}
+
+ >>> import yaml
+ >>> sFacts = open('/usr/local/etc/testforge/testforge.yml', 'rt').read()
+ >>> assert sFacts
+ >>> dFacts = yaml.safe_load(sFacts)
+
+=== .gitconfig ===
+
+We have a .gitconfig file in this directory that has our template
+of what we need up in the box to checkout from https://git.example.com
+You can edit the file and customize it, and we will use it as a
+Python string template, so look out for the {{{%()s}}} template fields.
+
+ >>> sDir = os.path.dirname(__file__)
+ >>> sFile = os.path.join(sDir, example.gitconfig')
+ >>> assert os.path.isfile(sFile), "ERROR: File not found " +sFile
+ >>> sGitConfig = open(sFile, 'r').read()
+ >>> assert sGitConfig, "ERROR: Nothing in " +sFile
+
+We will look for the environment variables:
+* {{{AAA_CERT}}} for the filename of your example certificate
+* {{{AAA_KEY}}} for the filename of your example key
+
+ >>> sCertFile = os.environ.get('AAA_CERT')
+ >>> assert sCertFile, "ERROR: we need AAA_CERT set in the environment"
+ >>> assert os.path.isfile(sCertFile), "ERROR: the AAA_CERT in the environment is not a file"
+
+ >>> sKeyFile = os.environ.get('AAA_KEY')
+ >>> assert sKeyFile, "ERROR: we need AAA_KEY set in the environment"
+ >>> assert os.path.isfile(sKeyFile), "ERROR: the AAA_KEY in the environment is not a file"
+
+ >>> sIdentityFile = os.path.expandvars('$HOME/.ssh/id_rsa')
+ >>> assert os.path.isfile(sIdentityFile), "ERROR: the file ~/.ssh/id_rsa is not a file"
+
+
+The directory we push to should have been created by Ansible.
+
+ >>> sBoxHome = dFacts['BOX_HOME']
+ >>> sDir = sBoxHome +'/etc/ssl/keys'
+ >>> run( "[ -d " +sDir +" ] || mkdir -p " +sDir) or None
+
+We will push these files up to the box so that we can use them.
+
+ >>> sUser = os.environ.get('USERNAME') or os.environ.get('USER')
+ >>> sTo = 'dd of=%s/%s@example.com-nodes.key' % (sDir, sUser,)
+ >>> ssh_run_with_stdin(sTo, sKeyFile) or None
+ >>> sTo = 'dd of=%s/%s@example.com-clcerts.key' % (sDir, sUser,)
+ >>> ssh_run_with_stdin(sTo, sCertFile) or None
+ >>> sTo = 'dd of=%s/%s@example.com-id_rsa' % (sDir, sUser,)
+ >>> ssh_run_with_stdin(sTo, sIdentityFile) or None
+ >>> sToDir = '%s/%s@*' % (sDir, sUser,)
+ >>> run( "chown 600 " +sToDir) or None
+
+Now we have the cert and key up we can write our templated {{{~/.gitconfig}}}
+
+ >>> sTempDir = os.environ.get('temp') or os.environ.get('TMP') or '/tmp'
+ >>> assert os.path.isdir(sTempDir)
+ >>> sFile = os.path.join(sTempDir, '.gitconfig')
+ >>> oFile = open(sFile, 'w')
+ >>> sGitConfig = sGitConfig % dict(USER=sUser, KEYSDIR=sDir,
+ ... BOX_HOME=sBoxHome)
+ >>> try:
+ ... oFile.write(sGitConfig)
+ ... finally:
+ ... oFile.close()
+ >>> assert os.path.isfile(sFile)
+ >>> sTo = sBoxHome +'/.gitconfig'
+ >>> ssh_run_with_stdin('dd of=' +sTo, sFile) or None
+ >>> sys.stderr.write("Wrote templated .gitconfig to " +sFile +'\n')
+
+QED.
diff --git a/overlay/Linux/usr/local/share/doc/txt/gitconfigV.txt b/overlay/Linux/usr/local/share/doc/txt/gitconfigV.txt
new file mode 100644
index 0000000..933dc69
--- /dev/null
+++ b/overlay/Linux/usr/local/share/doc/txt/gitconfigV.txt
@@ -0,0 +1,93 @@
+# -*-mode: doctest; tab-width: 0; py-indent-offset: 4; coding: utf-8-unix -*-
+
+== testserver box testing ==
+
+ >>> import os # doctest: +REPORT_ONLY_FIRST_FAILURE
+
+This is a Python doctest file that is executable documentation.
+It is built to run in the host against a Vagranted VirtualBox, and is run
+from the directory that contains the box's {{{.vagrant}}} subdirectory.
+
+ >>> import subprocess
+ >>> import sys
+ >>> import time
+
+And, now run tests locally
+
+ >>> sys.stderr.write("Running tests locally" +'\n')
+ 22
+
+=== Box settings ===
+
+We'll need the settings defined in {{{/usr/local/etc/testforge/testforge.yml}}}
+
+ >>> import yaml
+ >>> sFacts = open('/usr/local/etc/testforge/testforge.yml', 'rt').read()
+ >>> assert sFacts
+ >>> dFacts = yaml.safe_load(sFacts)
+
+=== .gitconfig ===
+
+We have a .gitconfig file in this directory that has our template
+of what we need up in the box to checkout from https://git.example.com
+You can edit the file and customize it, and we will use it as a
+Python string template, so look out for the {{{%()s}}} template fields.
+
+ >>> sDir = '/var/local/share/doc/txt'
+ >>> sFile = os.path.join(sDir, 'example.gitconfig')
+ >>> assert os.path.isfile(sFile), "ERROR: File not found " +sFile
+ >>> sGitConfig = open(sFile, 'r').read()
+ >>> assert sGitConfig, "ERROR: Nothing in " +sFile
+
+We will look for the environment variables:
+* {{{AAA_CERT}}} for the filename of your example certificate
+* {{{AAA_KEY}}} for the filename of your example key
+
+ >>> sCertFile = os.environ.get('AAA_CERT')
+ >>> assert sCertFile, "ERROR: we need AAA_CERT set in the environment"
+ >>> assert os.path.isfile(sCertFile), "ERROR: the AAA_CERT in the environment is not a file"
+
+ >>> sKeyFile = os.environ.get('AAA_KEY')
+ >>> assert sKeyFile, "ERROR: we need AAA_KEY set in the environment"
+ >>> assert os.path.isfile(sKeyFile), "ERROR: the AAA_KEY in the environment is not a file"
+
+ >>> sIdentityFile = os.path.expandvars('$HOME/.ssh/id_rsa')
+ >>> assert os.path.isfile(sIdentityFile), "ERROR: the file ~/.ssh/id_rsa is not a file"
+
+
+The directory we push to should have been created by Ansible.
+
+ >>> sBoxHome = dFacts['BOX_HOME']
+ >>> sDir = sBoxHome +'/etc/ssl/keys'
+ >>> run( "[ -d " +sDir +" ] || mkdir -p " +sDir) or None
+
+We will push these files up to the box so that we can use them.
+
+ >>> sUser = os.environ.get('USERNAME') or os.environ.get('USER')
+ >>> sTo = 'dd of=%s/%s@example.com-nodes.key' % (sDir, sUser,)
+ >>> ssh_run_with_stdin(sTo, sKeyFile) or None
+ >>> sTo = 'dd of=%s/%s@example.com-clcerts.key' % (sDir, sUser,)
+ >>> ssh_run_with_stdin(sTo, sCertFile) or None
+ >>> sTo = 'dd of=%s/%s@example.com-id_rsa' % (sDir, sUser,)
+ >>> ssh_run_with_stdin(sTo, sIdentityFile) or None
+ >>> sToDir = '%s/%s@*' % (sDir, sUser,)
+ >>> run( "chown 600 " +sToDir) or None
+
+Now we have the cert and key up we can write our templated {{{~/.gitconfig}}}
+
+ >>> sTempDir = os.environ.get('temp') or os.environ.get('TMP') or '/tmp'
+ >>> assert os.path.isdir(sTempDir)
+ >>> sFile = os.path.join(sTempDir, '.gitconfig')
+ >>> oFile = open(sFile, 'w')
+ >>> sGitConfig = sGitConfig % dict(USER=sUser, KEYSDIR=sDir,
+ ... BOX_HOME=sBoxHome)
+ >>> try:
+ ... oFile.write(sGitConfig)
+ ... finally:
+ ... oFile.close()
+ >>> assert os.path.isfile(sFile)
+ >>> sTo = sBoxHome +'/.gitconfig'
+ >>> ssh_run_with_stdin('dd of=' +sTo, sFile) or None
+ >>> sys.stderr.write("Wrote templated .gitconfig to " +sFile +'\n')
+
+QED.
diff --git a/overlay/Linux/usr/local/share/doc/txt/proxy2.txt b/overlay/Linux/usr/local/share/doc/txt/proxy2.txt
new file mode 100644
index 0000000..994227e
--- /dev/null
+++ b/overlay/Linux/usr/local/share/doc/txt/proxy2.txt
@@ -0,0 +1,21 @@
+# -*-mode: doctest; tab-width: 0; py-indent-offset: 4; coding: utf-8-unix -*-
+
+== proxy box testing ==
+
+This is a Python doctest file that is executable documentation.
+It is built to run against a Vagranted VirtualBox, and is run from the
+directory that contains the box's {{{.vagrant}}} subdirectory.
+
+ >>> import subprocess
+ >>> import sys
+ >>> import time
+
+And, now run tests against the box.
+
+ >>> print("Running tests against box", file=sys.stderr)
+
+We should be able to get a page from our proxy
+
+ >>> sUrl = 'http://' +myip +':3128/'
+ >>> print ssh_run('wget -O - -q %s | grep Polipo | head -1' % (sUrl,))
+ Welcome to Polipo
diff --git a/overlay/Linux/usr/local/share/doc/txt/proxy3.txt b/overlay/Linux/usr/local/share/doc/txt/proxy3.txt
new file mode 100644
index 0000000..d9a28bd
--- /dev/null
+++ b/overlay/Linux/usr/local/share/doc/txt/proxy3.txt
@@ -0,0 +1,47 @@
+#!/var/local/bin/testforge_run_doctest3.bash
+# -*-mode: doctest; tab-width: 0; py-indent-offset: 4; coding: utf-8-unix -*-
+
+== proxy testing ==
+
+This is a Python doctest file that is executable documentation.
+
+ >>> import os,sys # doctest: +REPORT_ONLY_FIRST_FAILURE
+
+And, now run tests against the box.
+
+ >>> sys.stderr.write("Running tests against box" +'\n')
+ 2...
+
+=== Box settings ===
+
+We'll need the settings defined in {{{/usr/local/etc/testforge/testforge.yml}}}
+
+ >>> import yaml
+ >>> sFacts = run('cat /usr/local/etc/testforge/testforge.yml')
+ >>> assert sFacts
+ >>> dFacts = yaml.safe_load(sFacts)
+
+=== /var/local/bin/proxy_hourly.bash ===
+
+ >>> os.system("/usr/local/bin/proxy_hourly.bash")
+ 0
+
+=== /var/local/src check ===
+
+ >>> os.chdir ('/usr/local/src')
+ >>> os.system('sh usr_local_proxy.bash check')
+ 0
+
+=== /var/local/src test ===
+
+ >>> os.chdir ('/usr/local/src')
+ >>> os.system('sh usr_local_proxy.bash test')
+ 0
+
+=== /var/local/src lint ===
+
+ >>> os.chdir ('/usr/local/src')
+ >>> os.system('sh usr_local_proxy.bash lint')
+ 0
+
+
diff --git a/overlay/Linux/usr/local/share/sed/fact_to_bash.sed b/overlay/Linux/usr/local/share/sed/fact_to_bash.sed
new file mode 100644
index 0000000..6f3e789
--- /dev/null
+++ b/overlay/Linux/usr/local/share/sed/fact_to_bash.sed
@@ -0,0 +1,7 @@
+# ROLE=proxy
+s@u*'@@g
+s@^ *@@
+s@\[@"@
+s@\]@"@
+s@, @ @g
+s@^@export @
diff --git a/overlay/Linux/usr/local/share/whonix-libvirt/xml/Kicksecure.xml b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Kicksecure.xml
new file mode 100644
index 0000000..0ad0446
--- /dev/null
+++ b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Kicksecure.xml
@@ -0,0 +1,80 @@
+
+ Kicksecure
+ Do not change any settings if you do not understand the consequences! Learn more: https://www.whonix.org/wiki/KVM#XML_Settings
+
+ 2097152
+ 2097152
+
+
+
+
+
+
+ 250
+
+ 1
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /dev/urandom
+
+
+
diff --git a/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Custom-Workstation.xml b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Custom-Workstation.xml
new file mode 100644
index 0000000..2864656
--- /dev/null
+++ b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Custom-Workstation.xml
@@ -0,0 +1,80 @@
+
+ Whonix-Custom-Workstation
+ Do not change any settings if you do not understand the consequences! Learn more: https://www.whonix.org/wiki/KVM#XML_Settings
+
+ 2097152
+ 2097152
+
+
+
+
+
+
+ 250
+
+ 1
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /dev/urandom
+
+
+
diff --git a/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-External.xml b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-External.xml
new file mode 100644
index 0000000..4083879
--- /dev/null
+++ b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-External.xml
@@ -0,0 +1,6 @@
+
+ Whonix-External
+
+
+
+
diff --git a/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Gateway.xml b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Gateway.xml
new file mode 100644
index 0000000..eeabeff
--- /dev/null
+++ b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Gateway.xml
@@ -0,0 +1,82 @@
+
+ Whonix-Gateway
+ Do not change any settings if you do not understand the consequences! Learn more: https://www.whonix.org/wiki/KVM#XML_Settings
+
+ 524288
+ 524288
+
+
+
+
+
+
+ 250
+
+ 1
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /dev/urandom
+
+
+
diff --git a/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Internal.xml b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Internal.xml
new file mode 100644
index 0000000..035cd91
--- /dev/null
+++ b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Internal.xml
@@ -0,0 +1,4 @@
+
+ Whonix-Internal
+
+
diff --git a/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Workstation.xml b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Workstation.xml
new file mode 100644
index 0000000..7fd883e
--- /dev/null
+++ b/overlay/Linux/usr/local/share/whonix-libvirt/xml/Whonix-Workstation.xml
@@ -0,0 +1,80 @@
+
+ Whonix-Workstation
+ Do not change any settings if you do not understand the consequences! Learn more: https://www.whonix.org/wiki/KVM#XML_Settings
+
+ 2097152
+ 2097152
+
+
+
+
+
+
+ 250
+
+ 1
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /dev/urandom
+
+
+
diff --git a/overlay/Linux/usr/local/src/helper-scripts/anondate b/overlay/Linux/usr/local/src/helper-scripts/anondate
new file mode 100755
index 0000000..7c6f1a1
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/anondate
@@ -0,0 +1,300 @@
+#!/bin/bash
+
+## Copyright (C) Amnesia
+## Copyright (C) 2014 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -o pipefail
+
+export TOR_LOG="/var/log/tor/log"
+if [ -d /var/lib/tor/data ] ; then
+ export TOR_DIR=/var/lib/tor/data
+ elif [ -d /var/lib/tor ] ; then
+ export TOR_DIR=/var/lib/tor
+ fi
+
+USAGE="
+ --has-consensus
+ --current-time-in-valid-range
+ --show-valid-after
+ --show-valid-until
+ --show-middle-range
+ --tor-cert-lifetime-invalid
+ --tor-cert-valid-after
+ --verified-only
+ --prefer-verified
+ --unverified-only
+ --user-permission
+ --group-permission
+"
+
+variables () {
+ [ -n "$TOR_RC" ] || TOR_RC="/etc/tor/torrc"
+ [ -n "$TOR_LOG" ] || TOR_LOG="/run/tor/log"
+ [ -n "$TOR_DIR" ] || TOR_DIR="/var/lib/tor"
+ [ -n "$TOR_DESCRIPTORS" ] || TOR_DESCRIPTORS="${TOR_DIR}/cached-microdescs"
+ [ -n "$NEW_TOR_DESCRIPTORS" ] || NEW_TOR_DESCRIPTORS="${TOR_DESCRIPTORS}.new"
+ [ -n "$TOR_CONSENSUS" ] || TOR_CONSENSUS="${TOR_DIR}/cached-microdesc-consensus"
+ [ -n "$TOR_UNVERIFIED_CONSENSUS" ] || TOR_UNVERIFIED_CONSENSUS="${TOR_DIR}/unverified-microdesc-consensus"
+ [ -n "$DATE_RE" ] || DATE_RE='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]'
+}
+
+parse_cmd_options() {
+ ## Thanks to:
+ ## http://mywiki.wooledge.org/BashFAQ/035
+
+ while :
+ do
+ case $1 in
+ --verbose)
+ echo "$SCRIPTNAME verbose output..."
+ echo "Script running as $(whoami)"
+ set -x
+ true "$0: $@"
+ shift
+ ;;
+ --has-consensus)
+ has_consensus_="true"
+ shift
+ ;;
+ --current-time-in-valid-range)
+ current_time_in_valid_range_="true"
+ shift
+ ;;
+ --show-valid-after)
+ show_valid_after_="true"
+ shift
+ ;;
+ --show-valid-until)
+ show_valid_until_="true"
+ shift
+ ;;
+ --show-middle-range)
+ show_middle_range_="true"
+ shift
+ ;;
+ --tor-cert-lifetime-invalid)
+ tor_cert_lifetime_invalid_="true"
+ shift
+ ;;
+ --tor-cert-valid-after)
+ tor_cert_valid_after_="true"
+ shift
+ ;;
+ --verified-only)
+ verified_only_="true"
+ shift
+ ;;
+ --prefer-verified)
+ prefer_verified_="true"
+ shift
+ ;;
+ --unverified-only)
+ unverified_only_="true"
+ shift
+ ;;
+ --user-permission)
+ user_permission_="true"
+ shift
+ ;;
+ --group-permission)
+ group_permission_="true"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ echo "$SCRIPTNAME unknown option: $1" >&2
+ exit 111
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ ## If there are input files (for example) that follow the options, they
+ ## will remain in the "$@" positional parameters.
+
+ if [ "$verified_only_" = "true" ]; then
+ consensus="$TOR_CONSENSUS"
+ elif [ "$prefer_verified_" = "true" ]; then
+ if [ -e "${TOR_CONSENSUS}" ]; then
+ consensus="$TOR_CONSENSUS"
+ else
+ consensus="$TOR_UNVERIFIED_CONSENSUS"
+ fi
+ elif [ "$unverified_only_" = "true" ]; then
+ consensus="$TOR_UNVERIFIED_CONSENSUS"
+ else
+ consensus="$TOR_CONSENSUS"
+ fi
+
+ if [ "$has_consensus_" = "true" ]; then
+ has_consensus
+ exit "$?"
+ fi
+ if [ "$current_time_in_valid_range_" = "true" ]; then
+ current_time_is_in_valid_range
+ exit "$?"
+ fi
+ if [ "$show_valid_after_" = "true" ]; then
+ show-valid-after
+ exit "$?"
+ fi
+ if [ "$show_valid_until_" = "true" ]; then
+ show-valid-until
+ exit "$?"
+ fi
+ if [ "$show_middle_range_" = "true" ]; then
+ show-middle-range
+ exit "$?"
+ fi
+ if [ "$tor_cert_lifetime_invalid_" = "true" ]; then
+ tor_cert_lifetime_invalid
+ exit "$?"
+ fi
+ if [ "$tor_cert_valid_after_" = "true" ]; then
+ tor_cert_valid_after
+ exit "$?"
+ fi
+ if [ "$user_permission_" = "true" ]; then
+ user_permission
+ exit "$?"
+ fi
+ if [ "$group_permission_" = "true" ]; then
+ group_permission
+ exit "$?"
+ fi
+
+ echo "USAGE: $0 $USAGE"
+ exit 1
+}
+
+root_check() {
+ if [ "$(id -u)" != "0" ]; then
+ echo "ERROR: Must run as root."
+ exit 112
+ fi
+}
+
+has_consensus() {
+ if [ ! -r "$consensus" ]; then
+ exit 4
+ fi
+ local grep_exit_code="0"
+ grep -qs "^valid-until ${DATE_RE}"'$' "$consensus" || { grep_exit_code="$?" ; true; };
+ if [ "$grep_exit_code" = "0" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+show-valid-after() {
+ vstart="$(sed -n "/^valid-after \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})" || exit 1
+ if [ "$show_valid_after_" = "true" ]; then
+ echo "$vstart"
+ fi
+}
+
+show-valid-until() {
+ vend="$(sed -n "/^valid-until \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})" || exit 1
+ if [ "$show_valid_until_" = "true" ]; then
+ echo "$vend"
+ fi
+}
+
+show-middle-range() {
+ show-valid-after
+ show-valid-until
+ vmid="$(date -ud "${vstart} -0130" +'%F %T')" || exit 1
+ if [ "$show_middle_range_" = "true" ]; then
+ echo "$vmid"
+ fi
+}
+
+current_time_is_in_valid_range() {
+ show-middle-range
+
+ ## {{ Sanity Test
+ ## Debugging.
+ #vend="2099-09-03 09:41:29"
+ vendchk="$(date -ud "${vstart} -0300" +'%F %T')"
+ if [ ! "${vend}" = "${vendchk}" ]; then
+ echo "ERROR: Unexpected valid-until: [${vend}] is not [${vstart} + 3h]"
+ return 1
+ fi
+ ## Sanity Test
+
+ curdate="$(date -u +'%F %T')"
+ ## Debugging.
+ #curdate="2099-09-03 09:41:29"
+
+ vendcons="$(date -ud "${vstart} -0230" +'%F %T')"
+ order="${vstart}
+${curdate}
+${vendcons}"
+ ordersrt="$(echo "${order}" | sort)"
+
+ if [ "${order}" = "${ordersrt}" ]; then
+ return 0
+ fi
+ echo WARN: failed Sanity Test
+ echo INFO: 'expected' $order
+ echo INFO: 'got ' $ordersrt
+ return 1
+}
+
+tor_cert_lifetime_invalid() {
+ if [ ! -r "$TOR_LOG" ]; then
+ return 3
+ fi
+
+ ## TODO:
+ ## To be sure that we only grep relevant information, we
+ ## should delete the log when Tor is started, which we do
+ ## TODO:
+ ## in 10-tor.sh.
+
+ ## Example Tor log:
+ ## Sep 03 10:32:59.000 [warn] Certificate already expired. Either their clock is set wrong, or your clock is wrong.
+ ## Sep 03 10:32:59.000 [warn] (certificate lifetime runs from Aug 16 00:00:00 2014 GMT through Jul 29 23:59:59 2015 GMT. Your time is Sep 03 10:32:59 2015 UTC.)
+
+ ## The log severity will be "warn" if bootstrapping with
+ ## authorities and "info" with bridges.
+ grep "\[\(warn\|info\)\] Certificate \(not yet valid\|already expired\)\." "${TOR_LOG}" | tail -n 1
+ if [ "$?" = "0" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+tor_cert_valid_after() {
+ if [ ! -r "$TOR_LOG" ]; then
+ return 3
+ fi
+
+ ## Only print the last = freshest match
+ sed -n 's/^.*certificate lifetime runs from \(.*\) through.*$/\1/p' "${TOR_LOG}" | tail -n 1
+
+ ## Example output:
+ ## Jun 16 00:00:00 2014 GMT
+ ## sudo: timestamp too far in the future: Jun 16 00:00:00 2014 GMT
+ return 0
+}
+
+user_permission() {
+ stat -c "%U" "$consensus"
+}
+
+group_permission() {
+ stat -c "%G" "$consensus"
+}
+
+root_check
+variables
+parse_cmd_options "$@"
diff --git a/overlay/Linux/usr/local/src/helper-scripts/anondate-tester b/overlay/Linux/usr/local/src/helper-scripts/anondate-tester
new file mode 100644
index 0000000..d131ab4
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/anondate-tester
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+export TOR_LOG="/var/log/tor/log"
+export TOR_DIR=/var/lib/tor/data
+
+cmd_item_list=(
+"--has-consensus"
+"--current-time-in-valid-range"
+"--show-valid-after"
+"--show-valid-until"
+"--show-middle-range"
+"--tor-cert-lifetime-invalid"
+"--tor-cert-valid-after"
+)
+
+for cmd_item in ${cmd_item_list[@]} ; do
+ output="$(/usr/local/lib64/helper-scripts/anondate $cmd_item $@)"
+ exit_code="$?"
+ if [ $exit_code -eq 0 ] ; then
+ echo "INFO: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+ echo "output: $output"
+ else
+ echo "WARN: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+ echo -n "exit_code: $exit_code "
+ echo "output: $output"
+ fi
+done
diff --git a/overlay/Linux/usr/local/src/helper-scripts/anondate-tester.diff b/overlay/Linux/usr/local/src/helper-scripts/anondate-tester.diff
new file mode 100644
index 0000000..d01123c
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/anondate-tester.diff
@@ -0,0 +1,45 @@
+*** anondate-tester.dst 2015-10-21 00:00:00.000000000 +0000
+--- anondate-tester 2020-12-20 22:02:49.000000000 +0000
+***************
+*** 1,8 ****
+--- 1,9 ----
+ #!/bin/bash
+
+ export TOR_LOG="/var/log/tor/log"
++ export TOR_DIR=/var/lib/tor/data
+
+ cmd_item_list=(
+ "--has-consensus"
+ "--current-time-in-valid-range"
+ "--show-valid-after"
+***************
+*** 11,22 ****
+ "--tor-cert-lifetime-invalid"
+ "--tor-cert-valid-after"
+ )
+
+ for cmd_item in ${cmd_item_list[@]} ; do
+! echo "cmd_item: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+! output="$(/usr/local/lib64/helper-scripts/anondate $cmd_item $@)"
+ exit_code="$?"
+! echo "output: $output"
+! echo "exit_code: $exit_code"
+! echo "----------"
+ done
+--- 12,27 ----
+ "--tor-cert-lifetime-invalid"
+ "--tor-cert-valid-after"
+ )
+
+ for cmd_item in ${cmd_item_list[@]} ; do
+! output="$(/usr/local/lib64/helper-scripts/anondate $cmd_item $@)"
+ exit_code="$?"
+! if [ $exit_code -eq 0 ] ; then
+! echo "INFO: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+! echo "output: $output"
+! else
+! echo "WARN: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+! echo -n "exit_code: $exit_code "
+! echo "output: $output"
+! fi
+ done
diff --git a/overlay/Linux/usr/local/src/helper-scripts/anondate-tester.dst b/overlay/Linux/usr/local/src/helper-scripts/anondate-tester.dst
new file mode 100755
index 0000000..346b616
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/anondate-tester.dst
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+export TOR_LOG="/var/log/tor/log"
+
+cmd_item_list=(
+"--has-consensus"
+"--current-time-in-valid-range"
+"--show-valid-after"
+"--show-valid-until"
+"--show-middle-range"
+"--tor-cert-lifetime-invalid"
+"--tor-cert-valid-after"
+)
+
+for cmd_item in ${cmd_item_list[@]} ; do
+ echo "cmd_item: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+ output="$(/usr/local/lib64/helper-scripts/anondate $cmd_item $@)"
+ exit_code="$?"
+ echo "output: $output"
+ echo "exit_code: $exit_code"
+ echo "----------"
+done
diff --git a/overlay/Linux/usr/local/src/helper-scripts/anondate.diff b/overlay/Linux/usr/local/src/helper-scripts/anondate.diff
new file mode 100644
index 0000000..6155cf2
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/anondate.diff
@@ -0,0 +1,307 @@
+*** anondate.dst 2015-10-21 00:00:00.000000000 +0000
+--- anondate-tester 2020-12-20 22:02:49.000000000 +0000
+***************
+*** 1,275 ****
+ #!/bin/bash
+
+! ## Copyright (C) Amnesia
+! ## Copyright (C) 2014 - 2020 ENCRYPTED SUPPORT LP
+! ## See the file COPYING for copying conditions.
+
+! set -o pipefail
+!
+! variables() {
+! [ -n "$TOR_RC" ] || TOR_RC="/etc/tor/torrc"
+! [ -n "$TOR_LOG" ] || TOR_LOG="/run/tor/log"
+! [ -n "$TOR_DIR" ] || TOR_DIR="/var/lib/tor"
+! [ -n "$TOR_DESCRIPTORS" ] || TOR_DESCRIPTORS="${TOR_DIR}/cached-microdescs"
+! [ -n "$NEW_TOR_DESCRIPTORS" ] || NEW_TOR_DESCRIPTORS="${TOR_DESCRIPTORS}.new"
+! [ -n "$TOR_CONSENSUS" ] || TOR_CONSENSUS="${TOR_DIR}/cached-microdesc-consensus"
+! [ -n "$TOR_UNVERIFIED_CONSENSUS" ] || TOR_UNVERIFIED_CONSENSUS="${TOR_DIR}/unverified-microdesc-consensus"
+! [ -n "$DATE_RE" ] || DATE_RE='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]'
+! }
+!
+! parse_cmd_options() {
+! ## Thanks to:
+! ## http://mywiki.wooledge.org/BashFAQ/035
+!
+! while :
+! do
+! case $1 in
+! --verbose)
+! echo "$SCRIPTNAME verbose output..."
+! echo "Script running as $(whoami)"
+! set -x
+! true "$0: $@"
+! shift
+! ;;
+! --has-consensus)
+! has_consensus_="true"
+! shift
+! ;;
+! --current-time-in-valid-range)
+! current_time_in_valid_range_="true"
+! shift
+! ;;
+! --show-valid-after)
+! show_valid_after_="true"
+! shift
+! ;;
+! --show-valid-until)
+! show_valid_until_="true"
+! shift
+! ;;
+! --show-middle-range)
+! show_middle_range_="true"
+! shift
+! ;;
+! --tor-cert-lifetime-invalid)
+! tor_cert_lifetime_invalid_="true"
+! shift
+! ;;
+! --tor-cert-valid-after)
+! tor_cert_valid_after_="true"
+! shift
+! ;;
+! --verified-only)
+! verified_only_="true"
+! shift
+! ;;
+! --prefer-verified)
+! prefer_verified_="true"
+! shift
+! ;;
+! --unverified-only)
+! unverified_only_="true"
+! shift
+! ;;
+! --user-permission)
+! user_permission_="true"
+! shift
+! ;;
+! --group-permission)
+! group_permission_="true"
+! shift
+! ;;
+! --)
+! shift
+! break
+! ;;
+! -*)
+! echo "$SCRIPTNAME unknown option: $1" >&2
+! exit 111
+! ;;
+! *)
+! break
+! ;;
+! esac
+! done
+!
+! ## If there are input files (for example) that follow the options, they
+! ## will remain in the "$@" positional parameters.
+!
+! if [ "$verified_only_" = "true" ]; then
+! consensus="$TOR_CONSENSUS"
+! elif [ "$prefer_verified_" = "true" ]; then
+! if [ -e "${TOR_CONSENSUS}" ]; then
+! consensus="$TOR_CONSENSUS"
+! else
+! consensus="$TOR_UNVERIFIED_CONSENSUS"
+ fi
+! elif [ "$unverified_only_" = "true" ]; then
+! consensus="$TOR_UNVERIFIED_CONSENSUS"
+! else
+! consensus="$TOR_CONSENSUS"
+! fi
+!
+! if [ "$has_consensus_" = "true" ]; then
+! has_consensus
+! exit "$?"
+! fi
+! if [ "$current_time_in_valid_range_" = "true" ]; then
+! current_time_is_in_valid_range
+! exit "$?"
+! fi
+! if [ "$show_valid_after_" = "true" ]; then
+! show-valid-after
+! exit "$?"
+! fi
+! if [ "$show_valid_until_" = "true" ]; then
+! show-valid-until
+! exit "$?"
+! fi
+! if [ "$show_middle_range_" = "true" ]; then
+! show-middle-range
+! exit "$?"
+! fi
+! if [ "$tor_cert_lifetime_invalid_" = "true" ]; then
+! tor_cert_lifetime_invalid
+! exit "$?"
+! fi
+! if [ "$tor_cert_valid_after_" = "true" ]; then
+! tor_cert_valid_after
+! exit "$?"
+! fi
+! if [ "$user_permission_" = "true" ]; then
+! user_permission
+! exit "$?"
+! fi
+! if [ "$group_permission_" = "true" ]; then
+! group_permission
+! exit "$?"
+! fi
+!
+! echo "No option chosen." 2>&1
+! exit 1
+! }
+!
+! root_check() {
+! if [ "$(id -u)" != "0" ]; then
+! echo "ERROR: Must run as root."
+! exit 112
+! fi
+! }
+!
+! has_consensus() {
+! if [ ! -r "$consensus" ]; then
+! exit 4
+! fi
+! local grep_exit_code="0"
+! grep -qs "^valid-until ${DATE_RE}"'$' "$consensus" || { grep_exit_code="$?" ; true; };
+! if [ "$grep_exit_code" = "0" ]; then
+! return 0
+! else
+! return 1
+! fi
+! }
+!
+! show-valid-after() {
+! vstart="$(sed -n "/^valid-after \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})" || exit 1
+! if [ "$show_valid_after_" = "true" ]; then
+! echo "$vstart"
+! fi
+! }
+!
+! show-valid-until() {
+! vend="$(sed -n "/^valid-until \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})" || exit 1
+! if [ "$show_valid_until_" = "true" ]; then
+! echo "$vend"
+! fi
+! }
+!
+! show-middle-range() {
+! show-valid-after
+! show-valid-until
+! vmid="$(date -ud "${vstart} -0130" +'%F %T')" || exit 1
+! if [ "$show_middle_range_" = "true" ]; then
+! echo "$vmid"
+! fi
+! }
+!
+! current_time_is_in_valid_range() {
+! show-middle-range
+!
+! ## {{ Sanity Test
+! ## Debugging.
+! #vend="2099-09-03 09:41:29"
+! vendchk="$(date -ud "${vstart} -0300" +'%F %T')"
+! if [ ! "${vend}" = "${vendchk}" ]; then
+! echo "ERROR: Unexpected valid-until: [${vend}] is not [${vstart} + 3h]"
+! exit 1
+! fi
+! ## }} Sanity Test
+!
+! curdate="$(date -u +'%F %T')"
+! ## Debugging.
+! #curdate="2099-09-03 09:41:29"
+!
+! vendcons="$(date -ud "${vstart} -0230" +'%F %T')"
+! order="${vstart}
+! ${curdate}
+! ${vendcons}"
+! ordersrt="$(echo "${order}" | sort)"
+!
+! if [ "${order}" = "${ordersrt}" ]; then
+! exit 0
+! else
+! exit 1
+! fi
+! }
+!
+! tor_cert_lifetime_invalid() {
+! if [ ! -r "$TOR_LOG" ]; then
+! exit 3
+! fi
+!
+! ## TODO:
+! ## To be sure that we only grep relevant information, we
+! ## should delete the log when Tor is started, which we do
+! ## TODO:
+! ## in 10-tor.sh.
+!
+! ## Example Tor log:
+! ## Sep 03 10:32:59.000 [warn] Certificate already expired. Either their clock is set wrong, or your clock is wrong.
+! ## Sep 03 10:32:59.000 [warn] (certificate lifetime runs from Aug 16 00:00:00 2014 GMT through Jul 29 23:59:59 2015 GMT. Your time is Sep 03 10:32:59 2015 UTC.)
+!
+! ## The log severity will be "warn" if bootstrapping with
+! ## authorities and "info" with bridges.
+! grep "\[\(warn\|info\)\] Certificate \(not yet valid\|already expired\)\." "${TOR_LOG}" | tail -n 1
+! if [ "$?" = "0" ]; then
+! return 0
+! else
+! return 1
+! fi
+! }
+!
+! tor_cert_valid_after() {
+! if [ ! -r "$TOR_LOG" ]; then
+! exit 3
+! fi
+!
+! ## Only print the last = freshest match
+! sed -n 's/^.*certificate lifetime runs from \(.*\) through.*$/\1/p' "${TOR_LOG}" | tail -n 1
+!
+! ## Example output:
+! ## Jun 16 00:00:00 2014 GMT
+! ## sudo: timestamp too far in the future: Jun 16 00:00:00 2014 GMT
+! }
+!
+! user_permission() {
+! stat -c "%U" "$consensus"
+! }
+!
+! group_permission() {
+! stat -c "%G" "$consensus"
+! }
+!
+! root_check
+! variables
+! parse_cmd_options "$@"
+--- 1,27 ----
+ #!/bin/bash
+
+! export TOR_LOG="/var/log/tor/log"
+! export TOR_DIR=/var/lib/tor/data
+
+! cmd_item_list=(
+! "--has-consensus"
+! "--current-time-in-valid-range"
+! "--show-valid-after"
+! "--show-valid-until"
+! "--show-middle-range"
+! "--tor-cert-lifetime-invalid"
+! "--tor-cert-valid-after"
+! )
+!
+! for cmd_item in ${cmd_item_list[@]} ; do
+! output="$(/usr/local/lib64/helper-scripts/anondate $cmd_item $@)"
+! exit_code="$?"
+! if [ $exit_code -eq 0 ] ; then
+! echo "INFO: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+! echo "output: $output"
+! else
+! echo "WARN: /usr/local/lib64/helper-scripts/anondate $cmd_item $@"
+! echo -n "exit_code: $exit_code "
+! echo "output: $output"
+ fi
+! done
diff --git a/overlay/Linux/usr/local/src/helper-scripts/anondate.dst b/overlay/Linux/usr/local/src/helper-scripts/anondate.dst
new file mode 100755
index 0000000..21d4d71
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/anondate.dst
@@ -0,0 +1,275 @@
+#!/bin/bash
+
+## Copyright (C) Amnesia
+## Copyright (C) 2014 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -o pipefail
+
+variables() {
+ [ -n "$TOR_RC" ] || TOR_RC="/etc/tor/torrc"
+ [ -n "$TOR_LOG" ] || TOR_LOG="/run/tor/log"
+ [ -n "$TOR_DIR" ] || TOR_DIR="/var/lib/tor"
+ [ -n "$TOR_DESCRIPTORS" ] || TOR_DESCRIPTORS="${TOR_DIR}/cached-microdescs"
+ [ -n "$NEW_TOR_DESCRIPTORS" ] || NEW_TOR_DESCRIPTORS="${TOR_DESCRIPTORS}.new"
+ [ -n "$TOR_CONSENSUS" ] || TOR_CONSENSUS="${TOR_DIR}/cached-microdesc-consensus"
+ [ -n "$TOR_UNVERIFIED_CONSENSUS" ] || TOR_UNVERIFIED_CONSENSUS="${TOR_DIR}/unverified-microdesc-consensus"
+ [ -n "$DATE_RE" ] || DATE_RE='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]'
+}
+
+parse_cmd_options() {
+ ## Thanks to:
+ ## http://mywiki.wooledge.org/BashFAQ/035
+
+ while :
+ do
+ case $1 in
+ --verbose)
+ echo "$SCRIPTNAME verbose output..."
+ echo "Script running as $(whoami)"
+ set -x
+ true "$0: $@"
+ shift
+ ;;
+ --has-consensus)
+ has_consensus_="true"
+ shift
+ ;;
+ --current-time-in-valid-range)
+ current_time_in_valid_range_="true"
+ shift
+ ;;
+ --show-valid-after)
+ show_valid_after_="true"
+ shift
+ ;;
+ --show-valid-until)
+ show_valid_until_="true"
+ shift
+ ;;
+ --show-middle-range)
+ show_middle_range_="true"
+ shift
+ ;;
+ --tor-cert-lifetime-invalid)
+ tor_cert_lifetime_invalid_="true"
+ shift
+ ;;
+ --tor-cert-valid-after)
+ tor_cert_valid_after_="true"
+ shift
+ ;;
+ --verified-only)
+ verified_only_="true"
+ shift
+ ;;
+ --prefer-verified)
+ prefer_verified_="true"
+ shift
+ ;;
+ --unverified-only)
+ unverified_only_="true"
+ shift
+ ;;
+ --user-permission)
+ user_permission_="true"
+ shift
+ ;;
+ --group-permission)
+ group_permission_="true"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ echo "$SCRIPTNAME unknown option: $1" >&2
+ exit 111
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ ## If there are input files (for example) that follow the options, they
+ ## will remain in the "$@" positional parameters.
+
+ if [ "$verified_only_" = "true" ]; then
+ consensus="$TOR_CONSENSUS"
+ elif [ "$prefer_verified_" = "true" ]; then
+ if [ -e "${TOR_CONSENSUS}" ]; then
+ consensus="$TOR_CONSENSUS"
+ else
+ consensus="$TOR_UNVERIFIED_CONSENSUS"
+ fi
+ elif [ "$unverified_only_" = "true" ]; then
+ consensus="$TOR_UNVERIFIED_CONSENSUS"
+ else
+ consensus="$TOR_CONSENSUS"
+ fi
+
+ if [ "$has_consensus_" = "true" ]; then
+ has_consensus
+ exit "$?"
+ fi
+ if [ "$current_time_in_valid_range_" = "true" ]; then
+ current_time_is_in_valid_range
+ exit "$?"
+ fi
+ if [ "$show_valid_after_" = "true" ]; then
+ show-valid-after
+ exit "$?"
+ fi
+ if [ "$show_valid_until_" = "true" ]; then
+ show-valid-until
+ exit "$?"
+ fi
+ if [ "$show_middle_range_" = "true" ]; then
+ show-middle-range
+ exit "$?"
+ fi
+ if [ "$tor_cert_lifetime_invalid_" = "true" ]; then
+ tor_cert_lifetime_invalid
+ exit "$?"
+ fi
+ if [ "$tor_cert_valid_after_" = "true" ]; then
+ tor_cert_valid_after
+ exit "$?"
+ fi
+ if [ "$user_permission_" = "true" ]; then
+ user_permission
+ exit "$?"
+ fi
+ if [ "$group_permission_" = "true" ]; then
+ group_permission
+ exit "$?"
+ fi
+
+ echo "No option chosen." 2>&1
+ exit 1
+}
+
+root_check() {
+ if [ "$(id -u)" != "0" ]; then
+ echo "ERROR: Must run as root."
+ exit 112
+ fi
+}
+
+has_consensus() {
+ if [ ! -r "$consensus" ]; then
+ exit 4
+ fi
+ local grep_exit_code="0"
+ grep -qs "^valid-until ${DATE_RE}"'$' "$consensus" || { grep_exit_code="$?" ; true; };
+ if [ "$grep_exit_code" = "0" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+show-valid-after() {
+ vstart="$(sed -n "/^valid-after \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})" || exit 1
+ if [ "$show_valid_after_" = "true" ]; then
+ echo "$vstart"
+ fi
+}
+
+show-valid-until() {
+ vend="$(sed -n "/^valid-until \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})" || exit 1
+ if [ "$show_valid_until_" = "true" ]; then
+ echo "$vend"
+ fi
+}
+
+show-middle-range() {
+ show-valid-after
+ show-valid-until
+ vmid="$(date -ud "${vstart} -0130" +'%F %T')" || exit 1
+ if [ "$show_middle_range_" = "true" ]; then
+ echo "$vmid"
+ fi
+}
+
+current_time_is_in_valid_range() {
+ show-middle-range
+
+ ## {{ Sanity Test
+ ## Debugging.
+ #vend="2099-09-03 09:41:29"
+ vendchk="$(date -ud "${vstart} -0300" +'%F %T')"
+ if [ ! "${vend}" = "${vendchk}" ]; then
+ echo "ERROR: Unexpected valid-until: [${vend}] is not [${vstart} + 3h]"
+ exit 1
+ fi
+ ## }} Sanity Test
+
+ curdate="$(date -u +'%F %T')"
+ ## Debugging.
+ #curdate="2099-09-03 09:41:29"
+
+ vendcons="$(date -ud "${vstart} -0230" +'%F %T')"
+ order="${vstart}
+${curdate}
+${vendcons}"
+ ordersrt="$(echo "${order}" | sort)"
+
+ if [ "${order}" = "${ordersrt}" ]; then
+ exit 0
+ else
+ exit 1
+ fi
+}
+
+tor_cert_lifetime_invalid() {
+ if [ ! -r "$TOR_LOG" ]; then
+ exit 3
+ fi
+
+ ## TODO:
+ ## To be sure that we only grep relevant information, we
+ ## should delete the log when Tor is started, which we do
+ ## TODO:
+ ## in 10-tor.sh.
+
+ ## Example Tor log:
+ ## Sep 03 10:32:59.000 [warn] Certificate already expired. Either their clock is set wrong, or your clock is wrong.
+ ## Sep 03 10:32:59.000 [warn] (certificate lifetime runs from Aug 16 00:00:00 2014 GMT through Jul 29 23:59:59 2015 GMT. Your time is Sep 03 10:32:59 2015 UTC.)
+
+ ## The log severity will be "warn" if bootstrapping with
+ ## authorities and "info" with bridges.
+ grep "\[\(warn\|info\)\] Certificate \(not yet valid\|already expired\)\." "${TOR_LOG}" | tail -n 1
+ if [ "$?" = "0" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+tor_cert_valid_after() {
+ if [ ! -r "$TOR_LOG" ]; then
+ exit 3
+ fi
+
+ ## Only print the last = freshest match
+ sed -n 's/^.*certificate lifetime runs from \(.*\) through.*$/\1/p' "${TOR_LOG}" | tail -n 1
+
+ ## Example output:
+ ## Jun 16 00:00:00 2014 GMT
+ ## sudo: timestamp too far in the future: Jun 16 00:00:00 2014 GMT
+}
+
+user_permission() {
+ stat -c "%U" "$consensus"
+}
+
+group_permission() {
+ stat -c "%G" "$consensus"
+}
+
+root_check
+variables
+parse_cmd_options "$@"
diff --git a/overlay/Linux/usr/local/src/helper-scripts/apt-get-update-kill-helper b/overlay/Linux/usr/local/src/helper-scripts/apt-get-update-kill-helper
new file mode 100755
index 0000000..e0efafe
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/apt-get-update-kill-helper
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+kill -s sigterm "$1"
+
+exit 0
diff --git a/overlay/Linux/usr/local/src/helper-scripts/apt-get-update-simulate b/overlay/Linux/usr/local/src/helper-scripts/apt-get-update-simulate
new file mode 100755
index 0000000..f107e97
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/apt-get-update-simulate
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## Required to run apt-get dist-upgrade --simulate as user (non-root).
+## Required for whonixcheck function check_operating_system.
+## Exception to run /usr/bin/apt-get-update as user
+## is defined in /etc/sudoers.d/.
+
+sigterm_trap() {
+ if [ "$lastpid" = "" ]; then
+ exit 0
+ fi
+ ps -p "$lastpid" >/dev/null 2>&1
+ if [ ! "$?" = "0" ]; then
+ ## Already terminated.
+ exit 0
+ fi
+ kill -s sigterm "$lastpid"
+ exit "$?"
+}
+
+trap "sigterm_trap" SIGTERM SIGINT
+
+timeout_after="10"
+kill_after="5"
+
+timeout \
+ --kill-after="$kill_after" \
+ "$timeout_after" \
+ apt-get dist-upgrade --simulate &
+
+lastpid="$!"
+wait "$lastpid"
+
+exit "$?"
diff --git a/overlay/Linux/usr/local/src/helper-scripts/bashrc-terminal-emulator b/overlay/Linux/usr/local/src/helper-scripts/bashrc-terminal-emulator
new file mode 100755
index 0000000..34ec44b
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/bashrc-terminal-emulator
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+## Copyright (C) 2020 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## This script gets `source`ed.
+## Using both 'return 0' and 'exit 0' to support both, `source`ing as well as
+## executing this script.
+
+if [ -z "$PS1" ]; then
+ true "If not running interactively, don't do anything."
+ return 0
+ exit 0
+fi
+
+shopt -q login_shell
+var="$?"
+if [ "$var" = "0" ]; then
+ true "running in a login shell, don't do anything."
+ ## Login shells are greeted by /etc/motd.
+ return 0
+ exit 0
+fi
+
+## We run in a terminal emulator.
+
+if ! test -d /etc/update-motd.d ; then
+ return 0
+ exit 0
+fi
+
+run-parts /etc/update-motd.d || true
diff --git a/overlay/Linux/usr/local/src/helper-scripts/first-boot-skel b/overlay/Linux/usr/local/src/helper-scripts/first-boot-skel
new file mode 100755
index 0000000..a7b39e8
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/first-boot-skel
@@ -0,0 +1,111 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -x
+set -e
+
+if command -v qubesdb-read >/dev/null 2>&1 ; then
+ qubes_vm_type="$(qubesdb-read /qubes-vm-type)"
+fi
+
+cache_folder="/var/cache/anon-base-files"
+
+if [ "$qubes_vm_type" = "TemplateVM" ]; then
+ ## Separate done file for Qubes TemplateVMs to make this work with the
+ ## current home folder population for Qubes DispVMs.
+ ## https://github.com/QubesOS/qubes-core-agent-linux/blob/f380c346cf9af3f058b8ece853d7d4a5ece28815/misc/dispvm-prerun.sh#L6-L12
+ done_file="$cache_folder/first-boot-skel.TemplateVM.done"
+else
+ ## Non-Qubes-Whonix or non-Qubes TemplateVMs
+ done_file="$cache_folder/first-boot-skel.done"
+fi
+
+if [ -e "$done_file" ]; then
+ exit 0
+fi
+
+user_name="user"
+home_dir="/home/$user_name"
+
+if [ ! -d "$home_dir" ]; then
+ exit 0
+fi
+
+skel_folder="/etc/skel"
+
+if [ ! -d "$skel_folder" ]; then
+ exit 0
+fi
+
+pushd "$skel_folder"
+
+mkdir -p "$cache_folder"
+
+shopt -s dotglob
+shopt -s nullglob
+
+for fso in ./* ; do
+ true "fso: $fso"
+ ## Technically below for 'cp' it would also be possible to use '$fso' rather
+ ## than '$fso_basename', but the latter produces a prettier xtrace.
+ fso_basename="${fso##*/}"
+ if [ ".bashrc" = "$fso_basename" ]; then
+ ## We do not need /home/user/.bashrc.
+ ## /home/user/.bashrc is handled below.
+ continue
+ fi
+ if [ ".bashrc.whonix" = "$fso_basename" ]; then
+ ## We do not need /home/user/.bashrc.whonix.
+ ## /home/user/.bashrc is handled below.
+ continue
+ fi
+ if [ ".bashrc.whonix-orig" = "$fso_basename" ]; then
+ ## We do not need /home/user/.bashrc.whonix-orig.
+ ## /home/user/.bashrc is handled below.
+ continue
+ fi
+ if [ -d "$fso" ]; then
+ true "folder: yes"
+ cp --verbose --no-clobber --archive --parents --recursive "$fso_basename" "$home_dir"
+ chown --changes --recursive "$user_name:$user_name" "$home_dir/$fso_basename"
+ else
+ true "folder: no"
+ ## Require '--dereference' otherwise the 'chown' below could fail.
+ cp --verbose --no-clobber --archive --dereference "$fso_basename" "$home_dir"
+ chown --changes "$user_name:$user_name" "$home_dir/$fso_basename"
+ fi
+done
+
+if [ ! -f "$skel_folder/.bashrc.whonix-orig" ]; then
+ touch "$done_file"
+ exit 0
+fi
+if [ ! -f "$skel_folder/.bashrc.whonix" ]; then
+ touch "$done_file"
+ exit 0
+fi
+if [ ! -f "$skel_folder/.bashrc" ]; then
+ touch "$done_file"
+ exit 0
+fi
+
+if diff "$skel_folder/.bashrc.whonix" "$home_dir/.bashrc" >/dev/null ; then
+ ## no diff found
+ true "Already using Whonix $skel_folder/.bashrc.whonix. No need to copy $skel_folder/.bashrc.whonix."
+ touch "$done_file"
+ exit 0
+fi
+
+if diff "$skel_folder/.bashrc.whonix-orig" "$home_dir/.bashrc" >/dev/null ; then
+ ## no diff found
+ true "Overwriting default $home_dir/.bashrc ( which matches $skel_folder/.bashrc.whonix-orig ) with $skel_folder/.bashrc.whonix."
+ cp --verbose --archive "$skel_folder/.bashrc.whonix" "$home_dir/.bashrc"
+ chown --changes "$user_name:$user_name" "$home_dir/.bashrc"
+else
+ ## a diff was found
+ true "User customized $home_dir/.bashrc. Keeping it."
+fi
+
+touch "$done_file"
diff --git a/overlay/Linux/usr/local/src/helper-scripts/leak-tests/exhaustive_ip_send.py b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/exhaustive_ip_send.py
new file mode 100755
index 0000000..057383d
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/exhaustive_ip_send.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python3 -u
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+import sys
+from scapy.all import *
+
+#define the target gateway & data payload
+target = "scanme.nmap.org"
+#target = "45.33.32.156"
+
+data = "testing"
+
+#define packet
+ip = IP()
+
+#define packet parameters
+ip.dst = target
+
+#loop through all IP packet types
+for ip_type in range(0,255):
+ ip.proto = ip_type
+ send(ip/data)
diff --git a/overlay/Linux/usr/local/src/helper-scripts/leak-tests/simple_ping.py b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/simple_ping.py
new file mode 100755
index 0000000..31101fa
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/simple_ping.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python3 -u
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+# Since it will be useful to know something about the script,
+# for the later tests, the terms are defined here:
+# (A discussion of Python language structure is beyond
+# the scope of this document)
+
+# [1] http://en.wikipedia.org/wiki/Ipv4
+# [2] http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol
+# [3] http://en.wikipedia.org/wiki/IP_routing
+# [4] http://en.wikipedia.org/wiki/Ping
+# [5] http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#List_of_permitted_control_messages_.28incomplete_list.29
+# [6] http://www.secdev.org/projects/scapy/doc/usage.html#send-and-receive-packets-sr
+# [7] http://www.secdev.org/projects/scapy/doc/usage.html#stacking-layers
+
+import sys
+from scapy.all import *
+
+# define the target gateway & data payload
+target = "10.152.152.10"
+#target = "45.33.32.156"
+
+data = "testing"
+
+# define packets
+# These define two variables, that are set to the object types IP
+# and ICMP respectively. These objects in Scapy define the protocol
+# type for IP (default IPv4) [1] and ICMP [2] respectively.
+# And will send packets on the wire of these types when used.
+ip = IP()
+icmp = ICMP()
+
+# define packet parameters
+ip.dst = target
+
+# IP packets are used for routing [3] between networks on the Internet.
+# So, we assign the destination (dst) in the IP portion of the
+# packet we are going to assemble and send out.
+icmp.type = 8
+icmp.code = 0
+
+# Defines the type of ICMP message to send out. The ..8 type.. is
+# a type defined as ..echo request.., e.g. a simple ping [4].
+# See a list here of various types of ICMP [5] messages here.
+
+# The sr1() [6] command will ..send and receive network traffic,
+# returning the 1st packet received...
+# The notation of ..ip/icmp/data.. is the notation for encapsulation
+# of various instances of networking protocols [7].
+# Read it right to left: ..data encapsulated inside an ICMP message
+# and encapsulated inside an IP datagram...
+test_ping = sr1(ip/icmp/data)
+
+if isinstance(test_ping, types.NoneType):
+ print("No response")
+else:
+# Prints a short report on the packet received (if any).
+ test_ping.summary()
diff --git a/overlay/Linux/usr/local/src/helper-scripts/leak-tests/tcp_test.py b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/tcp_test.py
new file mode 100755
index 0000000..a485a46
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/tcp_test.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python3 -u
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+import sys
+from scapy.all import *
+
+#define the target gateway & data payload
+target = "scanme.nmap.org"
+#target = "45.33.32.156"
+
+data = "testing"
+
+#define packets
+ip = IP()
+tcp = TCP()
+
+#define packet parameters
+ip.dst = target
+
+#loop through all TCP ports
+for tcp_port in range(0,65535):
+ tcp.dport = tcp_port
+ send(ip/tcp/data)
diff --git a/overlay/Linux/usr/local/src/helper-scripts/leak-tests/udp_test.py b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/udp_test.py
new file mode 100755
index 0000000..cd74a5b
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/leak-tests/udp_test.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python3 -u
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+import sys
+from scapy.all import *
+
+#define the target gateway & data payload
+target = "scanme.nmap.org"
+#target = "45.33.32.156"
+
+data = "testing"
+
+#define packets
+ip = IP()
+udp = UDP()
+
+#define packet parameters
+ip.dst = target
+
+#loop through all TCP ports
+for udp_port in range(0,65535):
+ udp.dport = udp_port
+ send(ip/udp/data)
diff --git a/overlay/Linux/usr/local/src/helper-scripts/pkg_manager_running_check b/overlay/Linux/usr/local/src/helper-scripts/pkg_manager_running_check
new file mode 100755
index 0000000..9bc074b
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/pkg_manager_running_check
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+check_package_manager_running_helper() {
+ if [ -f "/run/package_manager_lock" ]; then
+ check_apt_get_exit_code="/run/package_manager_lock exists."
+ package_manager_waiting_msg="Lock file \
+/run/package_manager_lock exists. Waiting for it to be removed..."
+ package_manager_waiting_msg_x="$package_manager_waiting_msg"
+ return 0
+ fi
+
+ local fuser_exit_code
+ fuser_exit_code=0
+ sudo --non-interactive fuser /var/lib/dpkg/lock /var/cache/apt/archives/lock &>/dev/null || { fuser_exit_code="$?" ; true; };
+
+ ## If a package manager is running:
+ ## sudo --non-interactive fuser /var/lib/dpkg/lock /var/cache/apt/archives/lock ; echo $?
+ ## /var/lib/dpkg/lock: 15601
+ ## /var/cache/apt/archives/lock: 15601
+ ## 0
+ ##
+ ## If no package manager is running:
+ ## sudo --non-interactive fuser /var/lib/dpkg/lock /var/cache/apt/archives/lock ; echo $?
+ ## 1
+
+ if [ "$fuser_exit_code" = "0" ]; then
+ check_apt_get_exit_code="1"
+ else
+ check_apt_get_exit_code="0"
+ fi
+
+ if [ ! "$check_apt_get_exit_code" = "0" ]; then
+ ## package_manager_waiting_msg used by cli-only applications.
+ package_manager_waiting_msg="A package manager (such as apt-get) is currently running. Waiting for it to finish...
+
+If you are not aware of any package mangers running, exit now, find out if there are any issues with dpkg or apt-get. Run in the terminal for example:
+sudo dpkg --audit
+sudo dpkg --configure -a
+sudo apt-get dist-upgrade
+
+Technical Info:
+\"sudo --non-interactive fuser /var/lib/dpkg/lock /var/cache/apt/archives/lock\" exit code: $fuser_exit_code"
+ ## package_manager_waiting_msg_x used applications using msgcollector.
+ package_manager_waiting_msg_x="
A package manager (such as apt-get) is currently running. Waiting for it to finish...
+
+If you are not aware of any package mangers running, exit now, find out if there are any issues with dpkg or apt-get. Run in the terminal for example:
+sudo dpkg --audit
+sudo dpkg --configure -a
+sudo apt-get dist-upgrade
+
+Technical Info:
+\"sudo --non-interactive fuser /var/lib/dpkg/lock /var/cache/apt/archives/lock\" exit code: $fuser_exit_code
"
+ else
+ package_manager_waiting_msg="No package manger currently running. \
+You should not see this message. Please report this bug!"
+ package_manager_waiting_msg_x="$package_manager_waiting_msg"
+ fi
+}
diff --git a/overlay/Linux/usr/local/src/helper-scripts/pre.bsh b/overlay/Linux/usr/local/src/helper-scripts/pre.bsh
new file mode 100755
index 0000000..d8b6542
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/pre.bsh
@@ -0,0 +1,276 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## The idea of this bash fragment is:
+## Say nothing, if everything goes well, but dump everything on error.
+
+## It allows to easily look inside the xtrace of a (Debian maintainer) script,
+## when the DEBDEBUG environment variable is set to 1.
+
+## To use it in other scripts, use something like this:
+# if [ -f /usr/local/lib64/helper-scripts/pre.bsh ]; then
+# source /usr/local/lib64/helper-scripts/pre.bsh
+# fi
+
+## Error log:
+## - implement trap ERR if function errorhandlergeneral does not exist
+## - implements a simple error handler if non exists
+## - run silent by default
+## - write xtrace to temporary log
+## - show full xtrace on unexpected non-zero exit code
+## - show exit code on unexpected non-zero exit code
+## - run syntax check "bash -n" on this script
+## - run syntax check "bash -n" on the script that sourced this script
+
+## DEBDEBUG:
+##
+## enable xtrace (-x) for maintainer script when DEBDEBUG environment
+## variable is set to 1.
+## For example:
+## sudo DEBDEBUG=1 dpkg -i /path/to/package.deb
+
+## SKIP_SCRIPTS
+##
+## The SKIP_SCRIPTS environment variable to skip scripts by name
+## For example:
+## sudo DEBDEBUG=1 SKIP_SCRIPTS=" security-misc.postinst " dpkg -i /path/to/package.deb
+##
+## another example:
+##
+## export DEBDEBUG=1
+## export SKIP_SCRIPTS+=" security-misc.postinst "
+## sudo -E dpkg -i /path/to/package.deb
+
+## Colorful output: provides color function
+
+## Shell options: enables errtrace
+
+## Configuration Folders
+##
+## For example if the name of the package is 'security-misc':
+## - /etc/security-misc_maint.d/*.conf
+## - /usr/local/etc/security-misc_maint.d/*.conf
+##
+## For example if the name of the script is 'panic-on-oops':
+## - /etc/panic-on-oops_pre.d/*.conf
+## - /usr/local/etc/panic-on-oops_pre.d/*.conf
+
+## {{{ pre.bsh 1.0
+
+## bash script fragment
+
+colors() {
+ if [ "$TERM" = "" ]; then
+ return 0
+ fi
+
+ ## Thanks to:
+ ## http://mywiki.wooledge.org/BashFAQ/037
+ ## Variables for terminal requests.
+ [[ -t 2 ]] && {
+ alt=$( tput smcup || tput ti ) # Start alt display
+ ealt=$( tput rmcup || tput te ) # End alt display
+ hide=$( tput civis || tput vi ) # Hide cursor
+ show=$( tput cnorm || tput ve ) # Show cursor
+ save=$( tput sc ) # Save cursor
+ load=$( tput rc ) # Load cursor
+ bold=$( tput bold || tput md ) # Start bold
+ stout=$( tput smso || tput so ) # Start stand-out
+ estout=$( tput rmso || tput se ) # End stand-out
+ under=$( tput smul || tput us ) # Start underline
+ eunder=$( tput rmul || tput ue ) # End underline
+ reset=$( tput sgr0 || tput me ) # Reset cursor
+ blink=$( tput blink || tput mb ) # Start blinking
+ italic=$( tput sitm || tput ZH ) # Start italic
+ eitalic=$( tput ritm || tput ZR ) # End italic
+ [[ $TERM != *-m ]] && {
+ red=$( tput setaf 1|| tput AF 1 )
+ green=$( tput setaf 2|| tput AF 2 )
+ yellow=$( tput setaf 3|| tput AF 3 )
+ blue=$( tput setaf 4|| tput AF 4 )
+ magenta=$( tput setaf 5|| tput AF 5 )
+ cyan=$( tput setaf 6|| tput AF 6 )
+ }
+ white=$( tput setaf 7|| tput AF 7 )
+ default=$( tput op )
+ eed=$( tput ed || tput cd ) # Erase to end of display
+ eel=$( tput el || tput ce ) # Erase to end of line
+ ebl=$( tput el1 || tput cb ) # Erase to beginning of line
+ ewl=$eel$ebl # Erase whole line
+ draw=$( tput -S <<< ' enacs
+ smacs
+ acsc
+ rmacs' || { \
+ tput eA; tput as;
+ tput ac; tput ae; } ) # Drawing characters
+ back=$'\b'
+ } 2>/dev/null ||:
+}
+
+source_config_folder() {
+ ## dpkg sets environment variables
+ ## example:
+ ## DPKG_MAINTSCRIPT_PACKAGE=security-misc
+
+ if [ "$DPKG_MAINTSCRIPT_PACKAGE" = "" ]; then
+ pre_bsh_settings_folder="${own_filename}_pre.d"
+ else
+ pre_bsh_settings_folder="${DPKG_MAINTSCRIPT_PACKAGE}_maint.d"
+ fi
+
+ ## example:
+ ## pre_bsh_settings_folder=security-misc_maint.d
+
+ shopt -s nullglob
+ local i
+
+ ## example:
+ ## /etc/panic-on-oops_pre.d/*.conf
+ ## /usr/local/etc/panic-on-oops_pre.d/*.conf
+
+ true "folder 1: /etc/${pre_bsh_settings_folder}/*.conf"
+ true "folder 2: /usr/local/etc/${pre_bsh_settings_folder}/*.conf"
+
+ for i in /etc/${pre_bsh_settings_folder}/*.conf /usr/local/etc/${pre_bsh_settings_folder}/*.conf; do
+ bash_n_exit_code="0"
+ bash_n_output="$(bash -n "$i" 2>&1)" || { bash_n_exit_code="$?" ; true; };
+ if [ ! "$bash_n_exit_code" = "0" ]; then
+ force_output "Invalid config file: $i
+ bash_n_exit_code: $bash_n_exit_code
+ bash_n_output:
+ $bash_n_output" >&2
+ rm -f "$TEMP_FILE_PRE_BSH"
+ exit 1
+ fi
+ source "$i"
+ done
+ shopt -u nullglob
+}
+
+check_scripts_to_skip() {
+ local skip_script
+ for skip_script in $SKIP_SCRIPTS; do
+ if [ "$skip_script" = "$own_filename" ]; then
+ force_output "INFO: Skipping $own_filename, because SKIP_SCRIPTS includes it."
+ rm -f "$TEMP_FILE_PRE_BSH"
+ exit 0
+ fi
+ done
+}
+
+disable_echo() {
+ if [ "$disabled_echo" = "true" ]; then
+ return 0
+ fi
+ exec 5>&1 1>> "$TEMP_FILE_PRE_BSH"
+ exec 6>&2 2>> "$TEMP_FILE_PRE_BSH"
+ disabled_echo=true
+}
+
+enable_echo() {
+ if [ "$disabled_echo" = "true" ]; then
+ exec 1>&5
+ exec 2>&6
+ disabled_echo=false
+ fi
+}
+
+force_output() {
+ if [ "$disabled_echo" = "true" ]; then
+ redisable_echo="true"
+ enable_echo
+ fi
+ echo "$@"
+ if [ "$redisable_echo" = "true" ]; then
+ disable_echo
+ fi
+}
+
+error_handler_pre() {
+ local exit_code="$?"
+ local last_err="$BASH_COMMAND"
+
+ if [ ! "$DEBDEBUG" = "1" ]; then
+ local output
+ output="$(cat "$TEMP_FILE_PRE_BSH")"
+ fi
+
+ if [ "$output" = "" ]; then
+ output="## See above."
+ fi
+
+ force_output "
+####################################################################
+## ${red}${bold}BEGIN ERROR in $0 detected!${reset}
+##
+## ${under}ERROR LOG${reset}:
+$output
+##
+## ${under}BASH_COMMAND${reset}: $BASH_COMMAND
+## ${under}EXIT_CODE${reset}: $exit_code
+##
+## ${red}${bold}END ERROR in $0 detected!${reset}
+## ${red}${bold}Please report this bug!${reset}
+####################################################################
+" 1>&2
+
+ rm -f "$TEMP_FILE_PRE_BSH"
+ exit 1
+}
+
+## config-package-dev doesn't like 'set -o pipefail'
+## http://mailman.mit.edu/pipermail/config-package-dev/2015-May/000041.html
+#set -o pipefail
+
+set -o errtrace
+
+TEMP_FILE_PRE_BSH="$(mktemp)"
+
+if test -o xtrace ; then
+ true "INFO: Setting DEBDEBUG to 1, because xtrace (-x) is set."
+ DEBDEBUG="1"
+fi
+
+if [ "$DEBDEBUG" = "1" ]; then
+ set -x
+fi
+
+if [ "$disable_echo" = "true" ]; then
+ disable_echo
+fi
+
+colors
+
+## {{ Set up error handler.
+if [ "$(type -t errorhandlergeneral)" = "function" ]; then
+ ## Function errorhandlergeneral exists (declared in
+ ## help-steps/pre). Prefer to use the more feature rich version of the error
+ ## handler.
+ trap "errorhandlergeneral" ERR
+else
+ ## Function errorhandlergeneral does not exist.
+
+ ## Check if any trap is already declared.
+ if [ "$(trap -p ERR)" = "" ]; then
+ ## No trap exist yet.
+ ## Fall back to a simpler error handler.
+ trap "error_handler_pre" ERR
+ fi
+fi
+## }}
+
+## syntax check this script
+bash -n "$BASH_SOURCE"
+
+## syntax check script that sourced this script
+bash -n "$0"
+
+own_filename="${0##*/}"
+
+source_config_folder
+
+check_scripts_to_skip
+
+## }}}
diff --git a/overlay/Linux/usr/local/src/helper-scripts/repair_torrc.py b/overlay/Linux/usr/local/src/helper-scripts/repair_torrc.py
new file mode 100755
index 0000000..c1880c2
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/repair_torrc.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python3 -u
+
+## Copyright (C) 2018 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+import os
+
+whonix = os.path.exists('/usr/share/anon-gw-base-files/gateway')
+if whonix:
+ torrc_file_path = '/usr/local/etc/torrc.d/40_tor_control_panel.conf'
+ torrc_user_file_path = '/usr/local/etc/torrc.d/50_user.conf'
+else:
+ torrc_file_path = '/etc/torrc.d/40_tor_control_panel.conf'
+ torrc_user_file_path = '/etc/torrc.d/50_user.conf'
+
+torrc_text = '# Do not edit this file!\n\
+# Please add modifications to the following file instead:\n'
+
+user_text = '# Tor user specific configuration file\n\
+#\n\
+# Add user modifications below this line:\n\
+############################################\n'
+
+'''Guarantee the existence of /etc/torrc.d/
+and the existence of /usr/local/etc/torrc.d/ if required.
+'''
+if not os.path.exists('/etc/torrc.d/'):
+ os.makedirs('/etc/torrc.d/')
+if whonix and not os.path.exists('/usr/local/etc/torrc.d/'):
+ os.makedirs('/usr/local/etc/torrc.d/')
+
+'''Guarantee the existence of:
+1. /etc/torrc.d/95_whonix.conf
+2. /etc/tor/torrc
+3. "%include /etc/torrc.d/95_whonix.conf" line in /etc/tor/torrc file
+
+In addition, we create 40_tor_control_panel.conf
+and 50_user.conf here if they do not exist.
+'''
+whonix_torrcd_path = '/etc/torrc.d/95_whonix.conf'
+
+if not os.path.exists('/etc/tor/torrc'):
+ with open('/etc/tor/torrc', "w+") as f:
+ if whonix:
+ f.write('%include {0}\n'.format(whonix_torrcd_path))
+ else:
+ f.write('%include {0}\n'.format(torrc_file_path))
+ f.write('%include {0}\n'.format(torrc_user_file_path))
+
+else:
+ torrcd_line_exists = 'include /etc/torrc.d' in open('/etc/tor/torrc', "r").read()
+ if not torrcd_line_exists:
+ with open('/etc/tor/torrc', "a") as f:
+ if whonix:
+ f.write('%include {0}\n'.format(whonix_torrcd_path))
+ else:
+ f.write('%include {0}\n'.format(torrc_file_path))
+ f.write('%include {0}\n'.format(torrc_user_file_path))
+
+if whonix and not os.path.exists(whonix_torrcd_path):
+ with open(whonix_torrcd_path, "w+") as f:
+ f.write('%include {0}\n'.format(torrc_file_path))
+ f.write('%include {0}\n'.format(torrc_user_file_path))
+
+torrc_text = '%s# %s\n' % (torrc_text, torrc_user_file_path)
+if not whonix:
+ torrc_text = (torrc_text +
+ 'Log notice file /run/tor/log\n')
+
+if not os.path.exists(torrc_file_path):
+ with open(torrc_file_path, "w+") as f:
+ f.write(torrc_text)
+
+if not os.path.exists(torrc_user_file_path):
+ with open(torrc_user_file_path, "w+") as f:
+ f.write(user_text)
+
diff --git a/overlay/Linux/usr/local/src/helper-scripts/settings_echo b/overlay/Linux/usr/local/src/helper-scripts/settings_echo
new file mode 100755
index 0000000..134d757
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/settings_echo
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -e
+
+## provides: check_tor_bootstrap_helper_variables
+source /usr/local/lib64/helper-scripts/tor_bootstrap_check.bsh
+
+check_tor_bootstrap_helper_variables
+
+echo "\
+GATEWAY_IP=\"$GATEWAY_IP\"
+gateway_control_port=\"$gateway_control_port\""
diff --git a/overlay/Linux/usr/local/src/helper-scripts/settings_echo.dst b/overlay/Linux/usr/local/src/helper-scripts/settings_echo.dst
new file mode 100755
index 0000000..6c04818
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/settings_echo.dst
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -e
+
+## provides: check_tor_bootstrap_helper_variables
+source /usr/local/lib/helper-scripts/tor_bootstrap_check.bsh
+
+check_tor_bootstrap_helper_variables
+
+echo "\
+GATEWAY_IP=\"$GATEWAY_IP\"
+gateway_control_port=\"$gateway_control_port\""
diff --git a/overlay/Linux/usr/local/src/helper-scripts/settings_environment_file_update b/overlay/Linux/usr/local/src/helper-scripts/settings_environment_file_update
new file mode 100755
index 0000000..2d3f452
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/settings_environment_file_update
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+## Copyright (C) 2017 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -e
+
+/usr/local/lib64/helper-scripts/settings_echo > /run/helper-scripts/settings_environment_file
diff --git a/overlay/Linux/usr/local/src/helper-scripts/settings_environment_file_update.dst b/overlay/Linux/usr/local/src/helper-scripts/settings_environment_file_update.dst
new file mode 100755
index 0000000..ebe7d00
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/settings_environment_file_update.dst
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+## Copyright (C) 2017 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+set -e
+
+/usr/local/lib/helper-scripts/settings_echo > /run/helper-scripts/settings_environment_file
diff --git a/overlay/Linux/usr/local/src/helper-scripts/te_pe_tb_check b/overlay/Linux/usr/local/src/helper-scripts/te_pe_tb_check
new file mode 100755
index 0000000..9f94f88
--- /dev/null
+++ b/overlay/Linux/usr/local/src/helper-scripts/te_pe_tb_check
@@ -0,0 +1,233 @@
+#!/bin/bash
+
+## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP
+## See the file COPYING for copying conditions.
+
+## Exit codes of this script get interpreted by sdwdate.
+## exit 0
+## exit 1: wait, retry and warning icon
+## exit 2: wait, retry and error icon
+
+set -o pipefail
+set -e errtrace
+
+error_handler() {
+ local exit_code="$?"
+ echo "\
+BASH_COMMAND: $BASH_COMMAND
+exit_code: $exit_code"
+}
+
+trap "error_handler" ERR
+
+source /usr/local/lib64/helper-scripts/tor_enabled_check
+source /usr/local/lib64/helper-scripts/pkg_manager_running_check
+source /usr/local/lib64/helper-scripts/tor_bootstrap_check.bsh
+
+te_pe_tb_check() {
+ if [ -f "/usr/share/anon-gw-base-files/gateway" ]; then
+ VM="Gateway"
+ elif [ -f "/usr/share/anon-ws-base-files/workstation" ]; then
+ VM="Workstation"
+ else
+ VM="Could not determine if this is gateway or workstation. Please report this bug."
+ fi
+
+ clock_causes="\
+
Possible causes:
+- The host clock is wrong -> shut down the VM, fix the clock in the host and restart the VM.
+- The VM clock is wrong -> manually fix the clock. Restart Tor if necessary. Then restart sdwdate.
+- A host clock attack succeeded.
+- A hardware issue (for example bios clock issues). "
+
+ ## Debugging.
+ true "$FUNCNAME: CURL: $CURL"
+ true "$FUNCNAME: LD_PRELOAD: $LD_PRELOAD"
+
+ if [ -e /usr/share/timesanitycheck/shared ]; then
+ ## provides: time_sanity_check
+ ## sets: time_sanity_check_exit_code
+ ## sets: time_sanity_check_msg_static
+ source /usr/share/timesanitycheck/shared
+ time_sanity_check
+ if [ "$time_sanity_check_exit_code" = "0" ]; then
+ echo "$time_sanity_check_msg_static" >&2
+ else
+ echo "$time_sanity_check_msg_static
+$clock_causes"
+ timesanitycheck_static_timestamp_based_failed="true"
+ if [ "$VM" = "Gateway" ]; then
+ exit 1
+ fi
+ fi
+ fi
+
+ ## Sets: TOR_ENABLED
+ check_tor_enabled_do
+
+ if [ "$TOR_ENABLED" = "1" ]; then
+ ## Ok.
+ true
+ else
+ if [ -f /usr/share/whonix/marker ]; then
+ echo "Tor is disabled. Please enable Tor using whonixsetup. \
+Start Menu -> System -> Anon Connection Wizard or in Terminal: sudo whonixsetup"
+ else
+ echo "Tor is disabled. Please enable Tor in the Tor config."
+ fi
+
+ exit 1
+ fi
+
+ ## sets: check_apt_get_exit_code
+ ## sets: package_manager_waiting_msg
+ #check_package_manager_running_helper ## pkg_manager_running_check
+ #if [ "$check_apt_get_exit_code" = "0" ]; then
+ #true "Package manager not busy, ok."
+ #else
+ #echo "$package_manager_waiting_msg"
+
+ #exit 2
+ #fi
+
+ ## sets: check_bootstrap_helper_script
+ ## sets: lastpid
+ ## sets: tor_bootstrap_percent
+ ## sets: tor_bootstrap_status
+ check_tor_circuit_established ## tor_bootstrap_check.bsh
+
+ ## $tor_circuit_established_check_exit_code on timeout returns:
+ ## - 124 if sigterm was sufficient
+ ## - 137 if needed to use kill.
+
+ for invalid_exit_code in "124" "137" "254" ; do
+ if [ "$tor_circuit_established_check_exit_code" = "$invalid_exit_code" ]; then
+ echo "Tor Bootstrap Result: \
+ ERROR ($tor_circuit_established_check_exit_code). Please report this bug!"
+ exit 1
+ fi
+ done
+
+ if [ "$tor_circuit_established_check_exit_code" = "255" ]; then
+ if [ "$VM" = "Gateway" ]; then
+ echo "Tor Bootstrap Result: \
+Tor's Control Port could not be reached. "
+ elif [ "$VM" = "Workstation" ]; then
+ if [ -f /usr/share/whonix/marker ]; then
+ echo "Tor Bootstrap Result: \
+Tor's Control Port could not be reached. \
+ Did you start Gateway beforehand? \
+ Please run whonixcheck on Gateway."
+ else
+ echo "Tor Bootstrap Result: \
+Tor's Control Port could not be reached. \
+ Did you start Gateway beforehand?"
+ fi
+ else
+ if [ -f /usr/share/whonix/marker ]; then
+ echo "Tor Bootstrap Result: \
+Tor's Control Port could not be reached. \
+ Did you start Gateway beforehand? \
+ Please run whonixcheck on Gateway.
+ $FUNCNAME: This is neither a gateway nor a workstation. Please report this bug!"
+ else
+ echo "Tor Bootstrap Result: \
+Tor's Control Port could not be reached. \
+ Did you start Gateway beforehand?
+ $FUNCNAME: This is neither a gateway nor a workstation. Please report this bug!"
+ fi
+ fi
+
+ exit 1
+ fi
+
+ if [ "$VM" = "Gateway" ]; then
+ check_tor_bootstrap_status
+ fi
+
+ ## When using an old Tor consensus which might be the case when no Tor
+ ## circuit has been established yet, there is no point to check Tor
+ ## consensus time as it might be outdated leading to concluding that the
+ ## clock is fast.
+ if [ "$tor_circuit_established" = "0" ]; then
+ if [ "$VM" = "Gateway" ]; then
+ echo "Tor is not yet fully bootstrapped. $tor_bootstrap_percent % done.\
+ Tor reports: $tor_bootstrap_status"
+ else
+ echo "Tor is not yet fully bootstrapped. Tor circuit: $tor_circuit_established_word."
+ fi
+ exit "2"
+ fi
+
+ ## If the static timestamp based time sanity check failed, there is no
+ ## need to run the Tor consensus based time sanity check. Avoiding
+ ## duplicate output.
+ if [ ! "$timesanitycheck_static_timestamp_based_failed" = "true" ]; then
+ ## sets: tor_consensus_valid_after_exit_code
+ ## sets: tor_consensus_valid_after_output
+ ## sets: tor_consensus_valid_after_unixtime
+ tor_consensus_valid-after
+
+ ## sets: tor_consensus_valid_until_exit_code
+ ## sets: tor_consensus_valid_until_output
+ ## sets: tor_consensus_valid_until_unixtime
+ tor_consensus_valid-until
+
+ current_unixtime="$(date +"%s")"
+
+ if [ "$tor_consensus_valid_after_exit_code" = "0" ] && [ "$tor_consensus_valid_until_exit_code" = "0" ]; then
+ clock_tor_consensus_check_result="ok"
+ if [ "$current_unixtime" -ge "$tor_consensus_valid_after_unixtime" ]; then
+ true
+ else
+ clock_tor_consensus_check_result="slow"
+ clock_tor_consensus_check_msg="The clock might be too slow. Clock is slower than consensus/valid-after $tor_consensus_valid_after_output. $clock_causes"
+ fi
+ if [ "$current_unixtime" -ge "$tor_consensus_valid_until_unixtime" ]; then
+ clock_tor_consensus_check_result="fast"
+ clock_tor_consensus_check_msg="The clock might be too fast. Clock is faster than consensus/valid-until $tor_consensus_valid_until_output. $clock_causes"
+ else
+ true
+ fi
+ elif [ "$tor_consensus_valid_after_exit_code" = "277" ] && [ "$tor_consensus_valid_until_exit_code" = "277" ]; then
+ clock_tor_consensus_check_result="noneyet"
+ clock_tor_consensus_check_msg="Might not have downloaded a Tor consensus yet."
+ else
+ clock_tor_consensus_check_result="error"
+ clock_tor_consensus_check_msg="Consensus time sanity check failed. $clock_causes"
+ fi
+
+ if [ "$clock_tor_consensus_check_result" = "ok" ]; then
+ clock_tor_consensus_check_result="ok"
+ clock_tor_consensus_check_msg="Clock within consensus parameters consensus/valid-after $tor_consensus_valid_after_output and consensus/valid-until $tor_consensus_valid_until_output."
+ fi
+
+ if [ "$clock_tor_consensus_check_result" = "ok" ]; then
+ echo "
$clock_tor_consensus_check_msg
" >&2
+ else
+ echo "
$clock_tor_consensus_check_msg
"
+ fi
+
+ ## TODO
+ ## Would have to parse tor_bootstrap_status.
+ ## In case Tor cannot fetch Tor consensus $tor_consensus_valid_after_exit_code /
+ ## $tor_consensus_valid_until_exit_code may be zero but $tor_consensus_valid_until_output
+ ## may be empty.
+ #if [ ! "$clock_tor_consensus_check_result" = "ok" ]; then
+ # if [ "$VM" = "Gateway" ]; then
+ # exit "1"
+ # fi
+ #fi
+ fi
+
+ if [ "$tor_circuit_established" = "1" ]; then
+ echo "