GCP Firewall Rules Explained | Google Cloud VPC Firewall Guide
Every GCP VM lives inside a VPC, and every packet that tries to reach or leave that VM is checked against firewall rules. Get the rules wrong and your application breaks, or worse, you leave a door open that should be closed. This guide explains how GCP firewall rules work from the ground up: priority, direction, targeting, and the mistakes that catch beginners out.
Simple explanation
Think of a firewall rule like a bouncer at a venue entrance. The bouncer checks a list: if your name (IP address, port, protocol) matches an entry, you get in. If you match a “do not admit” entry with a higher priority, you are turned away even if you also match an “admit” entry. If nothing on the list mentions you at all, the default answer is no.
GCP evaluates rules at the VPC network level. When a packet arrives or departs, GCP checks all rules that apply to that VM and direction, finds the highest-priority match, and acts on it.
Five things to know before going further:
- Firewall rules are stateful: if an inbound connection is allowed, return traffic is automatically permitted
- Rules match on direction, action, source or destination, protocol, port, and target VM
- Lower priority numbers mean higher precedence: priority 500 beats priority 1000
- A rule with no explicit VM target applies to every VM in the network
- Two implied rules cannot be deleted: deny all ingress and allow all egress
That is the whole model. Everything else on this page is detail on top of those five points.
How firewall rules work in GCP
When a packet tries to reach a VM, GCP goes through these steps in order:
- Determine direction. Is this traffic arriving at the VM (ingress) or leaving it (egress)?
- Find matching rules. GCP collects all firewall rules on the network, then filters to rules that match the packet’s direction, source or destination IP, protocol, and port, and that target this specific VM.
- Apply the highest-priority match. The rule with the lowest priority number wins. If it says ALLOW, the packet goes through. If it says DENY, the packet is dropped.
- Fall back to implied rules. If no explicit rule matches, the implied deny-all-ingress or allow-all-egress applies depending on direction.
- Allow return traffic automatically. Because rules are stateful, GCP tracks active connections. Return packets for an established session are permitted automatically.
A useful analogy for stateful rules: imagine you rang a doorbell (initiated a connection). Once the door is opened (the connection is allowed), you can have a full back-and-forth conversation through it without the bouncer checking each word. The session is tracked. Only when a brand-new visitor arrives does the bouncer check the list again.
This mental model covers almost every firewall scenario you will encounter. The rest of this page fills in the detail on each step.
Anatomy of a firewall rule
Here is a complete rule that allows HTTPS traffic from the internet to web servers. Read the command first, then the explanation of each field below it.
gcloud compute firewall-rules create allow-https \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--priority=1000Each flag corresponds to one part of the decision GCP makes when evaluating this rule:
- —network: which VPC this rule belongs to. Firewall rules are scoped to a single VPC and do not cross VPC boundaries.
- —direction=INGRESS: this rule applies to traffic arriving at VMs. EGRESS applies to traffic leaving them.
- —action=ALLOW: matching traffic is permitted. DENY blocks it instead.
- —rules=tcp:443: match TCP on port 443. You can use port ranges like
tcp:8080-8090, multiple protocols liketcp:443,udp:53, orallfor every protocol. - —source-ranges=0.0.0.0/0: allow from any source IP. In practice, restrict this to known ranges for anything sensitive. See private vs public IP addresses to understand which ranges are safe to expose.
- —target-tags=web-server: this rule only applies to VMs with the network tag
web-server. Omit this and the rule applies to every VM in the network. - —priority=1000: a lower number beats a higher number. Priority 500 overrides priority 1000 if both rules match the same traffic.
Because GCP firewall rules are stateful, the return packets for this HTTPS session (the TLS handshake, data transfers, connection teardown) are all automatically allowed back to the client. You write the rule once, for the direction in which the connection starts.
GCP firewall rules and OS-level firewalls like iptables operate independently. A packet must pass the GCP network firewall before it reaches the VM, and then the OS firewall applies on top. If a packet is allowed by a GCP rule but blocked by iptables on the VM, traffic is still dropped. Check both layers when troubleshooting connectivity.
Implicit default rules
Every VPC has two implied firewall rules that exist even if you have created no rules at all. You cannot delete them, but you can override them with any rule that has a lower priority number:
- Implied deny all ingress at priority 65534: blocks all inbound traffic that no explicit rule allows
- Implied allow all egress at priority 65535: allows all outbound traffic that no explicit rule denies
This asymmetry is intentional. The default posture is: your VMs can reach out to the internet and to other resources, but nothing external can initiate a connection to your VMs unless you explicitly permit it.
To open inbound access, create allow-ingress rules. Any rule you create at a typical priority like 1000 beats the implied deny at 65534. To lock down outbound access, create deny-egress rules with a priority lower than 65535.
Default VPC networks ship with pre-populated rules that allow SSH, RDP, ICMP, and internal traffic. These are useful for getting started but too permissive for production. Custom VPC networks start with only the implied rules, which is the safer starting point. The Network Security Best Practices guide covers how to harden both network types.
Ingress vs egress
Ingress is traffic arriving at your VM: a browser connecting to your web server, a monitoring agent sending data, a user starting an SSH session. Ingress rules define what is allowed in.
Egress is traffic leaving your VM: your application calling a database, a VM downloading a software package, a service querying an external API. Egress rules define what is allowed out.
Most beginners focus only on ingress, and for simple setups that is fine. The implied allow-all-egress means your VMs can reach anything by default. But in hardened environments, particularly production, regulated, or zero-trust architectures, restricting outbound traffic matters too. Common egress controls include:
- Blocking VMs from reaching arbitrary public IPs and routing approved outbound traffic through Cloud NAT
- Allowing egress only to specific internal CIDR ranges or service account targets
- Denying egress entirely from sensitive VMs that should only respond to inbound requests
Because rules are stateful, you do not need a matching egress rule to permit return traffic for an ingress-allowed connection. If you allow TCP:443 ingress, the SYN-ACK and data packets automatically flow back out. Stateful tracking handles this. Explicit egress rules are only needed when your VM initiates a brand-new outbound connection.
Targets, sources, and matching logic
A firewall rule applies to all VMs only when you omit the target. This distinction matters more than most beginners expect.
Targets: which VMs does this rule apply to?
You have three options:
- No target specified: the rule applies to every VM in the VPC. Use this only for rules that genuinely should be network-wide.
- Target network tag: the rule applies to VMs carrying a specific tag, such as
web-serverordatabase. See Network Tags for how tags work and their security limits. - Target service account: the rule applies to VMs running as a specific service account. Covered in the next section.
Sources: where is the traffic coming from?
For ingress rules, you specify the source. You can combine multiple source types:
- Source IP ranges: CIDR blocks like
10.0.0.0/8or0.0.0.0/0. Works for any source, internal or external. - Source tags: traffic from VMs carrying a specific tag. Convenient for VM-to-VM rules within the same VPC, but carries the same security caveat as target tags: anyone who can edit a VM can add that tag.
- Source service accounts: traffic from VMs running as a specific service account. Stronger than source tags for the same reason target service accounts are stronger.
If you create an allow-ingress rule from 0.0.0.0/0 with no target tag or service account, you have just opened that port to every VM in the VPC from anywhere on the internet. This is easy to do accidentally when testing, and it is one of the most common findings in cloud security audits. Always set a target unless the rule is deliberately network-wide.
Network tags vs service accounts for firewall rules
Both network tags and service accounts let you target firewall rules at specific VMs. The difference comes down to who controls them and how easy they are to misuse.
How network tags work
A network tag is a string you attach to a VM. Any user with the Compute Engine Instance Admin role (or broader) can add or remove tags from a VM at any time, including while it is running. If a firewall rule allows ingress from VMs tagged trusted-host, a developer with VM edit permissions can add that tag to any VM they manage and effectively grant themselves firewall access. For low-sensitivity rules this is acceptable. For access to databases, internal APIs, or management interfaces, this is a meaningful risk.
Read more about how tags work and their full security limitations on the Network Tags page.
How service account targeting works
A service account is set on a VM at creation time. Once the VM is running, you cannot change its service account without stopping and recreating it. This means a firewall rule targeting a specific service account cannot be gamed by editing VM metadata. An attacker would need to recreate the VM, which is a much more visible and auditable action.
# Allow app servers (by service account) to reach the database on port 5432
gcloud compute firewall-rules create app-to-db-sa \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:5432 \
--source-service-accounts=app-sa@my-project.iam.gserviceaccount.com \
--target-service-accounts=database-sa@my-project.iam.gserviceaccount.comWhich to choose
- Use tags when the access path is low-sensitivity, you need quick iteration, or you are managing a dev or staging environment where team members need flexibility
- Use service accounts when the rule controls access to sensitive resources (databases, internal APIs, secrets backends), when the environment is production or regulated, or when you cannot trust everyone who has VM edit permissions
A simple rule of thumb: if you would feel uncomfortable granting this access to the wrong VM, use service account targeting.
Priority and conflict resolution
Priority is a number between 0 and 65535. Lower means higher precedence. When GCP finds multiple rules matching the same traffic, the one with the lowest number wins, regardless of whether it is an ALLOW or a DENY.
Think of priority numbers like queue positions at a help desk. Position 1 gets served before position 1000. If person at position 500 says “deny this request” and person at position 1000 says “allow it”, position 500 wins because they were seen first.
This example shows a targeted deny overriding a broad allow:
# Allow HTTP from anywhere to web servers (priority 1000)
gcloud compute firewall-rules create allow-http \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:80 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--priority=1000
# Block a specific known-bad IP at higher priority (priority 500)
gcloud compute firewall-rules create block-bad-ip \
--network=production-vpc \
--direction=INGRESS \
--action=DENY \
--rules=all \
--source-ranges=192.0.2.1/32 \
--target-tags=web-server \
--priority=500Traffic from 192.0.2.1 hits the deny rule at priority 500 first, so it is blocked even though port 80 is otherwise open. Any other source IP reaches the allow rule at priority 1000 and is permitted.
A few things to watch for:
- If you have both an ALLOW and a DENY rule at the same priority targeting the same traffic, the outcome is undefined. One will win but you cannot predict which. Avoid ties.
- The implied rules (65534 and 65535) sit at the very bottom of the stack. Any rule you create at a normal priority overrides them.
- When auditing rules, order the list by priority.
gcloud compute firewall-rules listshows priority, but you need to read the full list carefully to understand the effective policy.
Common real-world use cases
Allow HTTPS to public web servers
The most common rule in any web-facing environment. Open TCP:443 from 0.0.0.0/0 to VMs tagged web-server. If you also serve HTTP, add TCP:80. Keep these rules targeted and do not open them to all VMs in the network.
gcloud compute firewall-rules create allow-https \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--priority=1000Restrict SSH to known IP ranges
Never open SSH to 0.0.0.0/0. Restrict access to your office CIDR range, your VPN exit IP, or use Cloud Identity-Aware Proxy (IAP) for SSH access without any external IP. IAP tunnels SSH over HTTPS through Google’s infrastructure and requires the IAP source range 35.235.240.0/20 as the allowed source.
gcloud compute firewall-rules create allow-ssh-office \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:22 \
--source-ranges=203.0.113.0/24 \
--target-tags=ssh-allowed \
--priority=1000Allow app servers to reach the database
Create a rule that allows only your app tier to reach database VMs on the specific port. Use service account targeting in production so the access boundary is tightly controlled and auditable.
gcloud compute firewall-rules create allow-app-to-db \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:5432 \
--source-tags=app-server \
--target-tags=database \
--priority=1000Block outbound internet access from internal workloads
For VMs that should never reach public IPs (batch jobs, internal services, sensitive compute workloads), create a deny-egress rule that blocks all traffic to 0.0.0.0/0. Combine this with Private Google Access so those VMs can still reach Google APIs without a public IP.
gcloud compute firewall-rules create deny-internet-egress \
--network=production-vpc \
--direction=EGRESS \
--action=DENY \
--rules=all \
--destination-ranges=0.0.0.0/0 \
--target-tags=internal-only \
--priority=1000Block a known bad IP
Set a deny rule at a lower priority number than your allow rules so it takes precedence. Use a narrow source range (/32 for a single IP) and a priority like 500 to ensure it overrides broader allow rules sitting at 1000.
When to create or review firewall rules
You will work with firewall rules in all of these situations:
- Exposing a service externally: any time a VM needs to accept traffic from the internet, you need an allow-ingress rule for the right port and protocol
- Restricting admin access: SSH, RDP, or any management port should have a targeted rule with a narrow source range, not a broad open rule
- Segmenting workloads inside a VPC: prevent your web tier from reaching your database directly, allow only the app tier. This is where subnets and firewall rules work together.
- Hardening a production environment: audit every rule, check for rules with no target tags, ensure egress is locked down for sensitive workloads, and verify priority ordering
- Troubleshooting blocked traffic: if an application cannot reach another service, the firewall is usually the first place to check. The Troubleshooting Network Issues page covers connectivity tests and log queries for this.
- Onboarding a new service: whenever a new VM or workload is added, review its firewall rules explicitly rather than relying on inherited broad rules
Firewall rules vs related concepts
Firewall rules vs routes
Routes decide where a packet goes: which next hop should handle it. Firewall rules decide whether a packet is allowed at all. A packet can be routed correctly to a VM and still be dropped by a firewall rule, or it can pass the firewall and be misrouted. You need both to work correctly. A common confusion: creating a route to a subnet does not open firewall access to VMs in that subnet.
Firewall rules vs network tags
Network tags are not a security mechanism by themselves. A tag is just a string. The security comes from the firewall rule that references the tag. If no firewall rule uses a tag, the tag has no effect on traffic. Think of tags as the labels that let firewall rules find the right VMs, not as access controls in their own right.
Firewall rules vs OS-level firewalls
GCP firewall rules are enforced at the network level, before traffic reaches the VM’s operating system. iptables, ufw, and Windows Firewall are enforced inside the VM. Both layers operate independently. Traffic allowed by GCP can still be blocked by the OS firewall; traffic blocked by GCP never reaches the OS firewall. Most teams manage GCP firewall rules centrally and leave the OS firewall either open or minimally configured. Running both tightly is valid defence-in-depth but adds operational complexity.
GCP firewall rules vs AWS security groups
If you have used AWS, the closest equivalent is a security group. Key differences: GCP firewall rules are defined at the VPC level and applied to VMs via tags or service accounts, while AWS security groups attach directly to instances or network interfaces. GCP uses explicit priority ordering to resolve conflicts, while AWS uses a simpler allow-only model with no priority between rules. Both are stateful. GCP’s tag-based model scales well for large fleets but requires care around who can manage tags.
Logging and troubleshooting
Firewall rule logging records which connections were allowed or denied. Logs go to Cloud Logging and are queryable for security auditing, incident investigation, and connectivity troubleshooting.
# Enable logging when creating a rule
gcloud compute firewall-rules create allow-https-logged \
--network=production-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--enable-logging
# Enable logging on an existing rule
gcloud compute firewall-rules update allow-https \
--enable-loggingLogging is opt-in by default. High-traffic rules (such as allowing all HTTP from the internet) can generate substantial log volume with a real cost at scale. Enable logging selectively on rules that matter for security: deny rules, rules protecting sensitive services, and rules you actively need to audit.
For connectivity troubleshooting, the most useful tool is Connectivity Test in the GCP Console under Network Intelligence. It simulates a packet flow between two endpoints and reports which firewall rule would allow or deny it, without sending real traffic. This is faster than reading through all rules manually. The Troubleshooting Network Issues guide covers this in detail, including how to read firewall log entries in Cloud Logging.
For internet egress control, firewall rules work alongside Cloud NAT and Private Google Access. Cloud NAT gives private VMs outbound internet access without a public IP. Private Google Access lets private VMs reach Google APIs (BigQuery, Cloud Storage, etc.) without traversing the public internet. Neither replaces firewall rules: they complement them.
Common beginner mistakes
- Opening SSH to 0.0.0.0/0. Port 22 open to the entire internet attracts constant brute-force attempts. Restrict SSH to a specific IP range (office CIDR, VPN exit IP), use Cloud IAP for browser-based SSH access with no external IP, or use a bastion host. In production, there is no good reason to allow SSH from any source.
- Forgetting that lower priority numbers win. “Priority” in GCP means the opposite of what the word usually implies. Priority 1 beats priority 1000. Many beginners expect a deny rule at priority 1000 to override a general allow, then find the traffic getting through because the allow is also at 1000 or lower. Always check both rule priorities explicitly.
- Creating rules without a target tag. A rule with no target applies to every VM in the network. If you create a broad allow rule intending it for one VM and forget to add a target tag, every VM silently receives that rule. This is how test rules end up in production networks. Always set a target tag or service account unless the rule is deliberately network-wide.
- Confusing routes and firewall rules. Routes control where packets go. Firewall rules control whether packets are allowed. Adding a route to a subnet does not open firewall access to VMs in that subnet. If traffic is not getting through, check both. See Routes in GCP for how routing and firewall rules interact.
- Using source tags for sensitive trust boundaries. If a firewall rule allows ingress from VMs tagged
trusted-app, anyone with Compute Engine edit permissions can add that tag to any VM and gain access. For rules protecting databases, internal APIs, or admin ports, use service account targeting instead. The access is then tied to IAM, not to mutable VM metadata. - Ignoring egress. The implied allow-all-egress means your VMs can call anything unless you restrict it. For workloads handling sensitive data or operating in regulated environments, leaving egress wide open is a risk. Review outbound rules alongside inbound ones.
Summary
- GCP firewall rules are stateful: allow an inbound connection and return traffic is automatically permitted with no separate egress rule needed
- Every VPC has two implied rules: deny all ingress (priority 65534) and allow all egress (priority 65535)
- Priority ranges from 0 to 65535. Lower numbers win when multiple rules match the same traffic.
- Rules target VMs via network tags or service accounts. Rules without a target apply to every VM in the VPC.
- Service account targeting is stronger than tag targeting for sensitive access paths because a VM’s service account cannot be changed while it is running
- Never open SSH or any admin port to 0.0.0.0/0. Restrict to known IP ranges or use Cloud IAP.
- Routes decide where traffic goes. Firewall rules decide whether it is allowed. Both must be correct.
- Enable firewall logging selectively on security-critical rules to avoid excess Cloud Logging cost
Frequently asked questions
Are GCP firewall rules stateful?
Yes. GCP firewall rules are stateful. If an inbound connection is allowed by a rule, the return traffic for that session is automatically permitted with no separate egress rule needed. For example, if you allow ingress TCP:443, the SYN-ACK and all subsequent packets for that session flow back to the client without any extra configuration.
What are the default firewall rules in a GCP VPC?
Every VPC has two implicit rules that cannot be deleted: deny all ingress (priority 65534) and allow all egress (priority 65535). By default, nothing external can reach your VMs, but your VMs can initiate outbound connections freely. You open inbound access by creating allow-ingress rules with lower priority numbers, which take precedence over the implicit deny.
What happens if multiple firewall rules match the same traffic?
GCP applies the rule with the lowest priority number. Priority ranges from 0 (highest precedence) to 65535 (lowest). If two rules both match the same packet, one ALLOW at priority 1000 and one DENY at priority 500, the DENY at priority 500 wins. If no explicit rule matches, the implied deny-all-ingress or allow-all-egress applies.
Should I use network tags or service accounts for firewall rules?
It depends on the sensitivity of the rule. Network tags are fine for general access patterns, but anyone with Compute Engine edit permissions can add or remove tags from a VM, which can grant unintended firewall access. Service account targeting is stronger because a VM's service account is set at creation and cannot be changed while the VM is running. For production databases, management interfaces, or any sensitive access path, use service account targeting.
Do GCP firewall rules apply to Cloud Run or only VMs?
GCP VPC firewall rules apply to VM instances (Compute Engine) and to workloads connected to a VPC via Serverless VPC Access, including Cloud Run, Cloud Functions, and App Engine standard environment. Fully managed services that sit outside your VPC (such as Cloud Run without a VPC connector) are not subject to your VPC firewall rules. Traffic to those services is controlled at the service level instead.