#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## Copyright (C) 2024 - 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
## See the file COPYING for copying conditions.

set -eu -o pipefail -o errtrace

# shellcheck source=../libexec/whonix-firewall/firewall-common
source /usr/libexec/whonix-firewall/firewall-common

variables_defaults(){
  common_variables_defaults_post

  ## 10.0.2.2/24: VirtualBox DHCP
  [ -n "${NON_TOR_GATEWAY:-}" ] || NON_TOR_GATEWAY="192.168.1.0/24 192.168.0.0/24 127.0.0.0/8 10.152.152.0/24 10.0.2.2/24"

  ## Space separated list of VPN servers, which Whonix-Gateway is allowed to connect to.
  [ -n "${VPN_SERVERS:-}" ] || VPN_SERVERS="198.252.153.26"

  ## Destinations you do not routed through VPN, only for Whonix-Gateway.
  ## 10.0.2.2/24: VirtualBox DHCP
  [ -n "${LOCAL_NET:-}" ] || LOCAL_NET="192.168.1.0/24 192.168.0.0/24 127.0.0.0/8 10.152.152.0/24 10.0.2.2/24"

  [ -n "${GATEWAY_ALLOW_INCOMING_RELATED_STATE:-}" ] || GATEWAY_ALLOW_INCOMING_RELATED_STATE=""
  [ -n "${GATEWAY_ALLOW_INCOMING_ICMP:-}" ] || GATEWAY_ALLOW_INCOMING_ICMP=0
  [ -n "${GATEWAY_ALLOW_INCOMING_ICMP_FRAG_NEEDED:-}" ] || GATEWAY_ALLOW_INCOMING_ICMP_FRAG_NEEDED=1
  [ -n "${GATEWAY_ALLOW_INCOMING_SSH:-}" ] || GATEWAY_ALLOW_INCOMING_SSH=0

  [ -n "${GATEWAY_ALLOW_INCOMING_FLASHPROXY:-}" ] || GATEWAY_ALLOW_INCOMING_FLASHPROXY="0"
  [ -n "${FLASHPROXY_PORT:-}" ] || FLASHPROXY_PORT="9000"
}

nft_defaults(){
  ## Flush old rules.
  $nftables_cmd add table inet nat
  $nftables_cmd add table inet filter
  $nftables_cmd add table ip6 nat

  $nftables_cmd flush table inet nat
  $nftables_cmd flush table inet filter
  $nftables_cmd flush table ip6 nat

  ## Set secure defaults.
  $nftables_cmd "add chain inet filter input { type filter hook input priority 0; policy drop; }"

  ## forward rules does not actually do anything if forwarding is disabled. Better be safe just in case.
  $nftables_cmd "add chain inet filter forward { type filter hook forward priority 0; policy drop; }"

  ## Will be lifted below.
  $nftables_cmd "add chain inet filter output { type filter hook output priority 0; policy drop; }"

  $nftables_cmd "add chain inet nat prerouting { type nat hook prerouting priority -100; }"
  $nftables_cmd "add chain inet nat output { type nat hook output priority -100; }"

  $nftables_cmd "add chain ip6 nat output { type nat hook output priority -100; }"
}

qubes() {
  qubes_gateway
}

nft_input_rules(){
  nft_input_rules_gateway
}

nft_input_defaults(){
  nft_input_defaults_gateway
}

nft_forward(){
  nft_forward_gateway
}

nft_output(){
  ## NO OUTPUT FILTERING YET!

  ## Allow outgoing traffic on VPN interface,
  ## if VPN_FIREWALL mode is enabled.
  ## DISABLED BY DEFAULT.
  if [ "$VPN_FIREWALL" = "1" ]; then
    $nftables_cmd add rule inet filter output oifname "$VPN_INTERFACE" counter accept
  fi

  ## Existing connections are accepted.
  $nftables_cmd add rule inet filter output ct state established counter accept

  if [ "$VPN_FIREWALL" = "1" ]; then
    ## Connections to VPN servers are allowed,
    ## when VPN_FIREWALL mode is enabled.
    ## DISABLED BY DEFAULT.
    for SERVER in $VPN_SERVERS; do
      $nftables_cmd add rule inet filter output ip daddr "$SERVER" counter jump accept
    done
  else
    ## Accept outgoing connections to local network, Whonix-Workstation and VirtualBox,
    ## unless VPN_FIREWALL mode is enabled.
    ## ENABLED BY DEFAULT.
    for NET in $NON_TOR_GATEWAY; do
      $nftables_cmd add rule inet filter output ip daddr "$NET" counter jump accept
    done
  fi

  ## clearnet user is allowed to connect any outside target.
  if [ -n "$CLEARNET_USER" ]; then
    $nftables_cmd add rule inet nat output skuid "$CLEARNET_USER" counter accept
  fi

  if [ "$VPN_FIREWALL" = "1" ]; then
    ## Reject all other outgoing traffic.
    $nftables_cmd add rule inet filter output counter reject
  fi
}

main() {
  get_options "${@}"
  if [ "$source_only" = "1" ]; then
    return 0
  fi
  init
  source_config_folder
  variables_defaults
  set -f
  nft_script_header
  firewall_mode_detection
  print_variables
  nft_defaults
  nft_drop_invalid_incoming_packages
  qubes
  nft_input_rules
  nft_input_defaults
  nft_forward
  nft_reject_invalid_outgoing_packages
  nft_output
  nft_check
  nft_load
  status_files
  end
}

main "${@}"
