================================================================
SD Tech Solutions — Geolocation Blocking Baseline  (v1.0)
================================================================
Block inbound connections from countries you never do business
with. This kills the bulk of drive-by scans and brute force at
the edge. Two recipes: (A) pfSense pfBlockerNG, (B) Linux
nftables + ipset. Outbound stays open unless stated otherwise.

POLICY DECISION FIRST
  Allow-list approach (recommended for BC SMBs):
    INBOUND: allow CA (+US if partners/travel), drop the rest.
  Remember: staff travelling abroad must use the VPN — the VPN
  subnet bypasses GeoIP (see note at bottom). Do not "fix" a
  traveller's access by opening their hotel country to all.

----------------------------------------------------------------
(A) pfSense — pfBlockerNG-devel
----------------------------------------------------------------
 1. System > Packages: install pfBlockerNG-devel.
 2. Firewall > pfBlockerNG > IP > GeoIP: register a (free)
    MaxMind license key, enable GeoIP.
 3. GeoIP category "Top Spammers" -> Action: Deny Inbound.
 4. Per-continent lists: set every continent to Deny Inbound,
    then whitelist Canada (and US if needed) via a permit alias.
 5. Firewall > Rules > WAN: pfBlockerNG auto-rules must sit ABOVE
    any port-forward/allow rules (Rule Order: pfB block rules first).
 6. Reports > Alerts: confirm blocks are logging; review monthly.

----------------------------------------------------------------
(B) Linux edge box — nftables + ipset country lists
----------------------------------------------------------------
# 1. Pull CIDR lists (ipdeny.com zone files) for allowed countries:
mkdir -p /etc/geoip && cd /etc/geoip
curl -sO https://www.ipdeny.com/ipblocks/data/aggregated/ca-aggregated.zone
# (repeat for us-aggregated.zone if allowing US)

# 2. /etc/nftables.d/geoip.nft
table inet geoip {
  set allow_cc {
    type ipv4_addr; flags interval; auto-merge
    # populated at boot by the refresh script below
  }
  chain inbound {
    type filter hook input priority -10; policy accept;
    ct state established,related accept
    iifname "lo" accept
    ip saddr @allow_cc accept
    # management/VPN ranges ALWAYS allowed (never lock yourself out):
    ip saddr { <VPN_SUBNET>, <TRUSTED_MGMT_IP>/32 } accept
    tcp dport { 22, 443, <SERVICE_PORTS> } drop     # geo-drop new conns
  }
}

# 3. Refresh script (cron weekly): rebuild the set from zone files
#    nft flush set inet geoip allow_cc
#    while read cidr; do nft add element inet geoip allow_cc { $cidr }; done \
#        < /etc/geoip/ca-aggregated.zone

TEST BEFORE TRUSTING (verify by content):
  - From a foreign VPS or phone hotspot w/ non-CA exit: connection
    to the service ports must TIME OUT.
  - From the VPN subnet: everything must still work.
  - Keep one out-of-band path (provider console) before enabling.

KNOWN GOTCHA (learned in production): if you geo-block SSH and
then travel, connect the VPN FIRST — the VPN range bypasses the
filter. That behaviour is intentional; do not remove it.

Deployed by SD Tech Solutions · sd-techsolutions.com
