#!/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 <adrelanos@riseup.net>
## 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
