#!/sbin/nft -f

# todo demander la liste complete des dns nationaux
# Profil par défaut du firewall. Les accès entrants et sortants sont très limités.
# On se trouve dans cet état :
# - au démarrage du poste
# - sur un réseau externe EDF, par exemple sur un réseau wifi ou filaire en télétravail

# Entrée
# Les paquets entrants sont refusés, sauf s'il s'agit d'un paquet venant d'une connexion initiée par le poste.
# Les paquets entrants marqués comme valides par le profil edf-vpn ou captive-portal

# Sortie
# Les accès sortants sont réduits au maximum.
# Sont autorisés :
# - le connectivity checker externe
# - le connectivity checker interne
# - les passerelles VPN
# - les requêtes DNS
# - les paquets sortants marqués comme valides par le profil edf-vpn
# - les paquets sortants marqués comme valides par le profil captive-portal

# Toujours effectuer un flush, pour supprimer les règles du profil précédent
flush ruleset

include "/etc/scibian-firewall/utils/variables"

table inet external {
    chain input {
        # Le policy drop va refuser tous les paquets qui ne sont pas explicitement autorisés
        # dans les règles ci dessous
        type filter hook input priority 0; policy drop;

        # On accepte les paquets des connexions initiées par le poste
        # Exemple : on accepte la réponse d'un serveur HTTP qu'on a requêté
        ct state established,related accept

        # On accepte les paquets marqués comme valides par le profil vpn en amont
        meta mark $packet_accepted_by_vpn accept

        # On accepte les paquets marqués comme valides par le profil vdi en amont
        meta mark $packet_accepted_by_vdi accept

        # On accepte les paquets entrants sur localhost
        iifname lo accept
    }

    chain output {
        # Le policy drop va refuser tous les paquets qui ne sont pas explicitement autorisés
        # dans les règles ci dessous
        type filter hook output priority 0; policy drop;

        # Les requêtes DNS (domain) sont autorisées
        # Nécessaire au bon fonctionnement du poste
        oifname $ethernet_interfaces udp dport domain accept
        oifname $wifi_interfaces udp dport domain accept

        # Ouverture de ICMP, pour que le poste puisse découvrir son réseau
        oifname $ethernet_interfaces ip protocol icmp accept
        oifname $wifi_interfaces ip protocol icmp accept

        # Note : Inutile d'autoriser les ports DHCP (bootpc et bootps),
        # car le DHCP tourne avec des raw sockets, non gérées par iptables/nftables
        # un peu de doc : https://unix.stackexchange.com/questions/556827/looking-for-a-simple-but-effective-firewall

        # Les requêtes vers les passerelles VPN sont acceptées
        # Il faut pouvoir se connecter au VPN depuis le profil external
        oifname $ethernet_interfaces ip daddr $vpn_gateways accept
        oifname $wifi_interfaces ip daddr $vpn_gateways accept

        # Les requêtes vers les connectivity checkers internes sont autorisés
        # Ils nous permettent de déterminer si le poste a accès au réseau EDF
        oifname $ethernet_interfaces ip daddr $internal_connectivity_check_ip tcp dport $internal_connectivity_check_port accept
        oifname $wifi_interfaces ip daddr $internal_connectivity_check_ip tcp dport $internal_connectivity_check_port accept

        # Les requêtes http(s) sont autorisées vers le détecteur de portail captif externe
        oifname $wifi_interfaces ip daddr $captive_portal_checkers tcp dport { 80, 443 } accept

        # On accepte les paquets marqués comme valides par le profil vpn en amont
        meta mark $packet_accepted_by_vpn accept

        # On accepte les paquets marqués comme valides par le profil captive-portal en amont
        meta mark $packet_accepted_by_captive accept

        # On accepte les paquets marqués comme valides par le profil vdi en amont
        meta mark $packet_accepted_by_vdi accept

        # On accepte les paquets sortants sur localhost
        oifname lo accept
    }

    chain forward {
        # Le poste n'est pas un routeur, on drop tous les paquets qui transitent via le poste
        # et qui ne lui sont pas destinés
        type filter hook forward priority 0; policy drop;
    }
}
