Defense in depth — five-layer model: VPC firewall + OS firewall + SQL Server auth + no public IP + VPC Service Controls
Operations and safety — when to use and avoid firewall tools; lockout scenarios; troubleshooting connectivity failures; alignment between GCP VPC and OS firewall layers
Glossary
Firewall
Software or hardware that filters network traffic based on rules (allow/deny by IP, port, protocol, direction). The first match in a rule chain wins; unmatched traffic follows the default policy.
Controls which traffic can reach your services. Misconfigured firewalls are the primary cause of “connection timed out” errors after deployment.
Cloud and OS firewalls are independent layers
Cloud VPCs (GCP, AWS, Azure) evaluate their own firewall rules before traffic reaches any VM. Configuring only the OS firewall while leaving the VPC layer open — or vice versa — still exposes or silently blocks traffic.
ufw (Uncomplicated Firewall)
A user-friendly frontend for iptables on Ubuntu/Debian. Manages ordered rule chains where the first match determines the action; handles rule persistence automatically.
The recommended firewall tool for single-VM Linux configurations. Use ufw status verbose to inspect rules before making changes.
Do not mix ufw and raw iptables rules
ufw manages iptables chains internally. Adding raw iptables rules on the same system can produce unpredictable ordering and conflict with ufw’s state tracking.
iptables / nftables
The low-level Linux packet filtering frameworks. iptables (legacy) and nftables (modern replacement) define rules in chains: INPUT (inbound), OUTPUT (outbound), FORWARD (routed). nftables supersedes iptables on modern kernels.
Required for complex configurations that ufw cannot express, such as multi-chain NAT rules or traffic shaping. On most production VMs ufw is sufficient.
Raw iptables rules do not survive reboot
Rules written directly via iptables exist only in memory. Use iptables-save > /etc/iptables/rules.v4 with iptables-persistent, or use ufw which persists rules automatically.
VPC firewall (GCP)
Google Cloud network-level firewall rules that filter traffic before it reaches VM instances. Managed via gcloud compute firewall-rules or Terraform. Rules are applied per-network and can target specific VM tags or service accounts.
Evaluated independently from the OS firewall. Both the VPC rule and the OS rule must allow traffic for a connection to succeed. A common failure: ufw allows port 1433 but the VPC firewall blocks it, causing nc -zv to time out from inside the VPC.
VPC firewall rule priorities
Rules are evaluated in ascending priority order (lower number = higher priority, range 0–65535). The default implicit rule is deny-all at priority 65535. An explicit allow rule at a lower priority number overrides it.
Windows Firewall (Windows Defender Firewall)
The built-in Windows packet filter managed via the NetSecurity PowerShell module (New-NetFirewallRule, Get-NetFirewallRule, Set-NetFirewallProfile) or legacy netsh advfirewall. Operates on three profiles applied based on detected network type: Domain, Private, and Public.
Controls inbound and outbound traffic on Windows VMs. Rules applied to the wrong profile (e.g., Domain only) have no effect when the VM is on a Public network.
Profile mismatch silently disables rules
A rule created without -Profile defaults to all profiles, but explicitly scoping to -Profile Domain means the rule is inactive on Private and Public networks. Always verify with Get-NetFirewallRule -DisplayName "name" | Format-List.
Default policy (allow vs. deny)
The firewall action applied to traffic that matches no explicit rule. Default deny blocks all unmatched traffic; default allow permits it. Production firewalls must default to deny on inbound traffic.
In ufw: set with ufw default deny incoming. In Windows Firewall: set with Set-NetFirewallProfile -DefaultInboundAction Block. In GCP VPC: the implicit rule at priority 65535 is deny-all ingress.
Enabling ufw without an SSH allow rule locks you out immediately
ufw enable with default-deny active blocks all inbound traffic including port 22. Always run sudo ufw allow from 35.235.240.0/20 to any port 22 proto tcp before ufw enable. Recovery requires GCP serial console or IAP tunnel.
IAP tunnel (Identity-Aware Proxy)
A Google Cloud proxy that brokers SSH sessions to VMs without requiring a public IP or an open port 22 on the internet. Traffic arrives at the VM from the fixed CIDR 35.235.240.0/20; the VPC firewall must allow TCP 22 from that range.
Used as the fourth defense-in-depth layer: removing the VM’s external IP entirely eliminates the public attack surface while preserving SSH access via gcloud compute ssh.
IAP requires a matching VPC firewall rule
Even with IAP enabled, gcloud compute ssh times out if no VPC firewall rule permits TCP 22 from 35.235.240.0/20. The OS-level SSH allow rule alone is insufficient.
Every production database should be accessible ONLY from authorized sources. A SQL Server port open to the internet is a security incident waiting to happen. Firewalls are your perimeter defense — and relying on only one layer is not enough.
The defense-in-depth model layers GCP VPC firewall rules (network level), OS-level firewall (ufw/Windows Firewall), application authentication, and IAP tunneling so that no single misconfiguration exposes a service.
flowchart TD
Internet["Internet / External Client"]
GCP["GCP VPC Firewall<br>(network perimeter)"]
OS["OS Firewall<br>ufw / Windows Firewall"]
App["Application Auth<br>SQL Server login / IAM"]
IAP["IAP Tunnel<br>(no public IP)"]
DB[("SQL Server / DB")]
Internet -->|"blocked unless explicitly allowed"| GCP
GCP -->|"allowed port 1433 from VPC subnet only"| OS
OS -->|"allowed from authorized internal IPs"| App
App -->|"strong credentials / service account"| DB
Internet -.->|"SSH via IAP"| IAP
IAP --> OS
Linux ufw tools
ufw (Uncomplicated Firewall) is a frontend to iptables designed to simplify firewall management on Linux. It maintains ordered rule chains: rules are evaluated top-to-bottom and the first match wins. On production VMs the correct baseline is default-deny inbound, default-allow outbound, with explicit allow rules for each required service and source range.
Linux | ufw | check firewall state
Use ufw status verbose to inspect current rules, default policies, and enabled state before making changes.
Check firewall status and active rules
sudo ufw status verbose
Status: activeLogging: on (low)Default: deny (incoming), allow (outgoing), deny (routed)New profiles: skipTo Action From-- ------ ----1433/tcp ALLOW IN 10.132.0.0/2422/tcp ALLOW IN 35.235.240.0/20
Linux | ufw | allow and deny rules
Inbound allow rules in ufw always filter by source IP, destination port, and protocol. Omitting the from clause opens the port to the entire internet — always specify a source range.
Allow SQL Server from a VPC subnet
sudo ufw allow from 10.132.0.0/24 to any port 1433 proto tcp
Allow SSH from the IAP IP range
sudo ufw allow from 35.235.240.0/20 to any port 22 proto tcp
Deny a specific source range
sudo ufw deny from 192.168.50.0/24 to any port 1433 proto tcp
Reject with an ICMP response (instead of silent drop)
reject sends a TCP RST or ICMP port-unreachable back to the sender, signaling a refused connection rather than a timeout. Use deny (silent drop) for internet-facing rules to avoid revealing open ports.
sudo ufw reject from 192.168.50.0/24 to any port 1433 proto tcp
Never allow a port without scoping the source
sudo ufw allow 1433 opens TCP port 1433 to every IP address on the internet. This is a critical misconfiguration for database ports.
Always scope allow rules to a source range
sudo ufw allow from 10.132.0.0/24 to any port 1433 proto tcp
Limit the source to the VPC subnet CIDR or the specific IAP range.
Flag
Syntax
Description
from <ip/cidr>
ufw allow from 10.0.0.0/8 to any port 22
Restrict rule to a source IP or CIDR range
to any port <n>
ufw allow from 10.0.0.0/8 to any port 1433
Target a specific destination port
proto tcp|udp
ufw allow from 10.0.0.0/8 to any port 53 proto udp
Restrict rule to a protocol
allow
ufw allow from ... to any port 22
Permit matching traffic
deny
ufw deny from 1.2.3.4 to any
Silently drop matching traffic
reject
ufw reject from 1.2.3.4 to any
Drop and reply with ICMP unreachable
Linux | ufw | default policies
Default policies define what happens to traffic that matches no explicit rule. Always set deny incoming before enabling ufw on a production server, then add explicit allow rules for each required service.
Set default deny incoming and allow outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing
Enable the firewall
Run this only after adding all required allow rules, especially SSH. Enabling ufw with no SSH allow rule in place will immediately terminate your remote session.
sudo ufw enable
ufw enable can lock you out of SSH
If no SSH allow rule exists before running ufw enable, remote access is lost immediately. The VM must be recovered via console or IAP.
Add the SSH allow rule before enabling
sudo ufw allow from 35.235.240.0/20 to any port 22 proto tcpsudo ufw enable
Verify rule is present with sudo ufw status numbered first.
Flag
Syntax
Description
default deny incoming
ufw default deny incoming
Block all inbound traffic not matched by a rule
default allow outgoing
ufw default allow outgoing
Allow all outbound traffic not matched by a rule
default deny outgoing
ufw default deny outgoing
Block all outbound (strict egress control)
default allow incoming
ufw default allow incoming
Allow all inbound (insecure — avoid in production)
Linux | ufw | delete and reset rules
Rules are managed by number in ufw. Always list numbered rules before deleting to avoid removing the wrong entry.
List rules with numbers
sudo ufw status numbered
Status: active To Action From -- ------ ----[ 1] 1433/tcp ALLOW IN 10.132.0.0/24[ 2] 22/tcp ALLOW IN 35.235.240.0/20
Delete a rule by number
sudo ufw delete 3
Reset all rules to factory defaults
sudo ufw reset
ufw reset removes all rules including SSH
Running ufw reset on a remote VM without console access will lock you out.
Disable ufw temporarily instead of resetting
sudo ufw disable
This stops enforcement without deleting rules, preserving the configuration for re-enable.
Flag
Syntax
Description
status numbered
ufw status numbered
List all rules with index numbers for deletion
delete <n>
ufw delete 3
Remove rule at position n
delete allow <port>
ufw delete allow 22
Remove allow rule matching port (if unique)
reset
ufw reset
Remove all rules and disable ufw
disable
ufw disable
Stop ufw enforcement without removing rules
Linux | ufw | logging
ufw writes to /var/log/ufw.log. Logging levels control verbosity: low logs blocked packets, medium adds allowed packets, high adds rate-limited packets.
Maximum verbosity — use for short debugging sessions only
PowerShell Windows Firewall tools
Windows Firewall (Windows Defender Firewall) is managed through the NetSecurity PowerShell module via cmdlets like New-NetFirewallRule, Get-NetFirewallRule, and Set-NetFirewallProfile. It operates on three profiles — Domain, Private, and Public — applied based on the detected network type.
PowerShell | Windows Firewall | inspect rules
Get-NetFirewallRule retrieves all firewall rules from the Windows Firewall policy store. Pipe with Where-Object to filter by state, direction, or action.
Get-NetFirewallRule -DisplayName "SQL Server - Pipeline" | Get-NetFirewallAddressFilter
LocalAddress : AnyRemoteAddress : 10.132.0.0/24
Flag
Syntax
Description
-DisplayName
Get-NetFirewallRule -DisplayName "name"
Filter by display name
-Name
Get-NetFirewallRule -Name "name"
Filter by internal rule name
-Direction
Get-NetFirewallRule -Direction Inbound
Filter by traffic direction
-Action
Get-NetFirewallRule -Action Allow
Filter by action (Allow / Block)
-Enabled
Get-NetFirewallRule -Enabled True
Filter by enabled state
-Profile
Get-NetFirewallRule -Profile Domain
Filter by profile (Domain/Private/Public)
PowerShell | Windows Firewall | create rules
New-NetFirewallRule adds inbound or outbound rules to the Windows Firewall policy. Always specify -RemoteAddress to scope the rule to a source subnet; omitting it allows any IP.
New-NetFirewallRule -Direction Inbound -LocalPort 1433 -Action Allow allows TCP 1433 from any source address on the internet. Do not omit -RemoteAddress for database or admin ports.
Apply rule only when connected to matching network profiles
-Enabled
-Enabled True|False
Create rule in enabled or disabled state
PowerShell | Windows Firewall | default policies
Set-NetFirewallProfile configures the default action for each of the three Windows Firewall profiles. In production, block all inbound by default and add explicit allow rules for each service.
Remove-NetFirewallRule is permanent and does not prompt by default
There is no undo. If you remove the wrong rule, you must recreate it manually.
Disable a rule first instead of removing it
Set-NetFirewallRule -DisplayName "SQL Server - Pipeline" -Enabled False
Disabling preserves the rule definition and allows re-enabling without reconfiguration.
Flag
Syntax
Description
-DisplayName
Remove-NetFirewallRule -DisplayName "name"
Remove by display name
-Name
Remove-NetFirewallRule -Name "name"
Remove by internal name
-Direction
Remove-NetFirewallRule -Direction Inbound
Remove all rules matching a direction
PowerShell / Linux | gcloud | firewall rules
GCP VPC firewall rules operate at the network level, before traffic reaches any VM’s OS firewall. They are evaluated independently from ufw or Windows Firewall — both layers must allow traffic for a connection to succeed. gcloud compute firewall-rules manages these rules from either Linux or PowerShell.
GCP VPC firewall and OS firewall are independent layers
A GCP firewall rule allowing port 1433 does not override an OS-level ufw deny rule, and vice versa. Both must permit the traffic. A common debugging pattern: ufw allows port 1433 but the GCP firewall blocks it at the network level, so nc -zv times out even from inside the VPC.
PowerShell / Linux | gcloud | list firewall rules
List all VPC firewall rules in the project
gcloud compute firewall-rules list \ --format="table(name,direction,allowed,sourceRanges)"
NAME DIRECTION ALLOW SRC_RANGESallow-iap-ssh INGRESS tcp:22 35.235.240.0/20allow-sql-pipeline INGRESS tcp:1433 10.132.0.0/24default-allow-internal INGRESS tcp,udp,icmp 10.128.0.0/9
PowerShell / Linux | gcloud | create firewall rules
Allow SSH from the IAP IP range
For iap-tunneling to work, a GCP firewall rule must allow TCP 22 from 35.235.240.0/20. Without this rule, gcloud compute ssh times out even if the VM is running and ufw allows SSH.
Deleting a GCP firewall rule takes effect immediately
Unlike OS-level firewall changes that require a service restart, GCP firewall rule deletions propagate within seconds and immediately block matching traffic.
Disable a rule instead of deleting during troubleshooting
This preserves the rule definition and allows re-enabling with --no-disabled.
Flag
Syntax
Description
--source-ranges
update --source-ranges 10.0.0.0/8
Replace source CIDR ranges
--allow
update --allow tcp:1433,tcp:1434
Replace allowed protocol/port list
--disabled
update --disabled
Disable the rule without deleting it
--no-disabled
update --no-disabled
Re-enable a disabled rule
--priority
update --priority 500
Change rule priority
Defense in depth
The most effective firewall strategy for production databases is layered: no single control point is trusted to be the sole barrier. Each layer operates independently, so a misconfiguration in one does not expose the database.
Never rely on a single firewall layer
If only the GCP VPC firewall blocks port 1433 and that rule is accidentally deleted or modified, the port becomes immediately accessible from the internal network. Each layer must function as if the others do not exist.
Apply all five layers simultaneously
GCP VPC firewall — block port 1433 from external IPs at the network level (manage declaratively with networking)
OS firewall (ufw / Windows Firewall) — block port 1433 from unauthorized internal IPs at the OS level
SQL Server login — require strong passwords and specific login names (see service-accounts-and-iam for IAM-based access)
No public IP — remove the VM’s external IP entirely; use IAP tunneling for SSH (see iap-tunneling)
VPC Service Controls — prevent data exfiltration from the project (see vpc-service-controls; GCP Enterprise tier required)
Warnings
Firewall changes can lock you out
Three operational mistakes regularly turn a routine firewall change into an outage:
Default-deny before SSH allow.ufw enable with no prior SSH allow rule blocks remote access immediately.
Treating cloud and host firewalls as one layer. Allowing port 1433 in ufw but not in the GCP VPC firewall, or the reverse, still blocks the connection.
Using raw iptables rules without persistence. Manual rules disappear on reboot unless they are explicitly saved and restored.
If you are working on a remote host, assume every firewall change is a potential self-lockout until both the access path and the rollback path are verified.
Stage firewall changes safely
Apply firewall changes in a sequence that preserves recovery:
Protect remote access first. Run ufw allow ssh before enabling a default-deny policy, and keep serial console or GCP IAP access available as a fallback.
Validate both enforcement layers. Confirm that the cloud firewall and the OS firewall both permit the protocol and source range you intend to use.
Persist host rules deliberately. Save raw iptables rules with iptables-save plus iptables-persistent, or use ufw so the persistence behavior is handled for you.
The safe pattern is to treat firewall policy as layered state that must survive both the immediate change and the next reboot.