Compute Engine

Using Networks and Firewalls

To manage traffic to and from your instances, use networks and firewalls to create rules that dictate how your instances interact with each other and with the Internet.

Networks and firewalls are global resources and are available to all resources in a project.

Prerequisites for this guide



Every instance is a member of a single network. A network performs the same function that a router does: it defines the network range and gateway IP address, handles communication between instances, and serves as a gateway between instances and other networks. A network is constrained to a single project; it cannot span projects. Any communication between instances in different networks, even within the same project, must be through external IP addresses. In the API, a network is represented by the Network resource.

The network exposes the following properties, which can also be set using the gcloud compute networks create command.


The network IP range for this network, in CIDR notation. You can change this, but you must use one of the standard private network address ranges. For example:


The gateway address for the network. For example:


The name must be unique in this project, from 1-63 characters long and match the regular expression: [a-z]([-a-z0-9]*[a-z0-9])? which has the following meaning:

  • The first character must be a lowercase letter,
  • All characters after the first—but before the last—must be a dash, lowercase letter, or digit,
  • The last character must be a lowercase letter or digit.

All projects include a default network named default with the following values:

  • IPv4Range -
  • gatewayIPv4 -
  • name - default

The default network also has the following firewall rules:

Allows network connections of any protocol and port between instances on the network.
Allows SSH connections from any source to any instance on the network over TCP port 22.
Allows RDP connections from any source to any instance on the network over TCP port 3389.
Allows ICMP traffic from any source to any instance on the network.

If you do not explicitly assign your instances to a network, all instances added to the project are automatically assigned to this default network in the instance's networkInterfaces.network property. An instance can be assigned only one network. Assign instances to different networks using the --network flag:

$ gcloud compute networks create NETWORK --range CIDR_RANGE # create a network
$ gcloud compute instances create INSTANCE --network NETWORK # add an instance to the network

By default, you can create up to five networks per project, including the default network. If you need more than five networks for your project, you can choose to request more quota.

Several firewall rules can be applied to the same network to describe which instances can accept what kinds of incoming traffic. A firewall rule has a reference to the network but a network does not have a list of firewall rules.


The following example requests information about the default network. You can also use the --format flag to choose how the output appears:

$ gcloud compute networks describe default --format json
  "IPv4Range": "",
  "creationTimestamp": "2014-11-25T14:51:07.686-08:00",
  "description": "Default network for myproject",
  "gatewayIPv4": "",
  "id": "18446744031643681077",
  "kind": "compute#network",
  "name": "projects/myproject/networks/default",
  "selfLink": "https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default"

Useful gcloud compute commands:

Note that there is no way to modify an existing network. You can modify the routes and firewall rules associated with a network, but you cannot change the address range or gateway of a network after the network has been established.

Add a new network

Every project starts with one network called default. The default network is automatically created for you, and you do not need to take any action to initialize it. For many Compute Engine users, the default network is all that is needed. The default network functions just like any network you would create, so you can add or remove firewall rules from it or delete it altogether.

You can create up to four additional networks for a single project to help manage your instances. Creating multiple networks for a project can help you isolate sets of instances, as instances in different networks can only communicate with each other through external IP addresses. For example, you might want to keep instances in your testing and production systems from talking to one another except through external IPs. Putting the instances in different networks can accomplish this.

When creating instances in multiple networks, note that instance names are unique across a project. You cannot use the same instance name for two instances in the same project, even if they are in different networks. To add a new network to a project, use the gcloud compute tool with the networks create command:

$ gcloud compute networks create NETWORK --range CIDR_RANGE

For example, to add a network called "production", execute the following, replacing the value for --range with a range of your choosing:

$ gcloud compute networks create production --range

To list the networks for your project, execute the networks list command:

$ gcloud compute networks list

When adding a network, you must specify the address range and/or gateway address for the network to the networks create command. To see a full list of values that you can set, run gcloud compute networks create --help.

Each network has its own firewall controlling connectivity. When you create a new network, there are no firewall rules permitting connections of any type. After creating a new network, you should create firewall rules for it. To create a rule for a network called example-network that allows TCP, UDP, and ICMP traffic between the instances on the network, execute the following firewalls-rules create command:

$ gcloud compute firewall-rules create internal --network example-network \
    --source-ranges --allow tcp,udp,icmp

You can also create a firewall rule that allows HTTP traffic from anywhere to all instances on the example-network network. Execute the following:

$ gcloud compute firewall-rules create web --network example-network --allow tcp:80

For more information on firewalls, see the Firewalls section.

In order for your network to be useful, you need to add instances to it. To add an instance to a network, use the --network flag during instance creation. For example, to add an instance named example-instance to the example-network network, execute the following:

$ gcloud compute instances create example-instance --network example-network

Delete a network

Before you can delete a network using gcloud compute or the API, you must first delete all firewall rules attached to that network, all instances that use that network, and all manually-created routes that apply to the network. Otherwise, you will get an error indicating that the network is in use.

After you delete all firewall rules and instances attached to the network, run the networks delete command to delete the network:

$ gcloud compute networks delete NETWORK

Set up a network proxy

You can design your network so that only one instance has external access, and all other instances in the network use that instance as a proxy server to the outside world. This is useful if you want to control access into or out of your network, or reduce the cost of paying for multiple external IP addresses.

This particular example discusses how to set up a network proxy on Compute Engine instances that use a Debian image. It uses a gateway instance as a Squid proxy server but this is only one way of setting up a proxy server.

To set up a Squid proxy server:

  1. Set up one instance with an external (static or ephemeral) IP address. For this example, name your instance gateway-instance.
  2. Set up one or more instances without external IP addresses by specifying gcloud compute instances create ... --no-address. For this example, call this instance hidden-instance.
  3. Learn how to ssh from one instance to another because you will not be able to ssh directly into your internal-only instances.
  4. Add a firewall to allow traffic on tcp:3128:

    $ gcloud compute firewall-rules create FIREWALL_RULE --network NETWORK --allow tcp:3128
  5. Install Squid on gateway-instance, and configure it to allow access from any machines on the shared network. This assumes that gateway-instance and hidden-instance are both connected to the default network, which enables them to connect to each other:

    user@gateway:~$ sudo apt-get install squid3
    # Enable any machine on the local network to use the Squid3 server
    sed -i 's:#\(http_access allow localnet\):\1:' /etc/squid3/squid.conf
    sed -i 's:#\(http_access deny to_localhost\):\1:' /etc/squid3/squid.conf
    sed -i 's:#\(acl localnet src*\):\1:' /etc/squid3/squid.conf
    sed -i 's:#\(acl localnet src*\):\1:' /etc/squid3/squid.conf
    sed -i 's:#\(acl localnet src*\):\1:' /etc/squid3/squid.conf
    sed -i 's:#\(acl localnet src fc00\:\:/7.*\):\1:' /etc/squid3/squid.conf
    sed -i 's:#\(acl localnet src fe80\:\:/10.*\):\1:' /etc/squid3/squid.conf
    # Prevent proxy access to metadata server
    user@gateway:~$ sudo cat <<EOF >>/etc/squid3/squid.conf
    acl to_metadata dst
    http_access deny to_metadata
    # Start Squid
    user@gateway:~$ sudo service squid3 start
  6. Configure hidden-instance to use gateway-instance as its proxy. ssh into hidden-instance and define its proxy URL addresses to point to gateway on port 3128 (the default Squid configuration) as shown here:

    user@gateway:~$ ssh hidden-instance
    user@hidden:~$ sudo -s
    echo "export http_proxy=\"http://gateway.$(dnsdomainname):3128\"" >> /etc/profile.d/proxy.sh
    echo "export https_proxy=\"http://gateway.$(dnsdomainname):3128\"" >> /etc/profile.d/proxy.sh
    echo "export ftp_proxy=\"http://gateway.$(dnsdomainname):3128\"" >> /etc/profile.d/proxy.sh
    echo "export no_proxy=,metadata,metadata.google.internal" >> /etc/profile.d/proxy.sh
    # Update sudoers to pass these env variables through
    cp /etc/sudoers /tmp/sudoers.new
    chmod 640 /tmp/sudoers.new
    echo "Defaults env_keep += \"ftp_proxy http_proxy https_proxy no_proxy"\" >>/tmp/sudoers.new
    chmod 440 /tmp/sudoers.new
    visudo -c -f /tmp/sudoers.new && cp /tmp/sudoers.new /etc/sudoers
  7. Exit sudo, load the variables, and run apt-get on hidden-instance. It should now work using gateway as a proxy. If gateway were not serving as a proxy, apt-get would not work because hidden-instance has no direct connection to the Internet.

    root@hidden:~$ exit
    user@hidden:~$ source ~/.profile
    user@hidden:~$ sudo apt-get update

Set up an external HTTP connection

The default firewall rules do not allow HTTP or HTTPS connections to your instances. However, it is fairly simple to add a rule that does allow them. Note that an instance must have an external IP address before it can receive traffic from outside its network.

You can add a firewall rule to allow HTTP or HTTPS connections through gcloud compute or the Google Developers Console. You can also add a firewall rule through the API.

gcloud compute

If you want to allow HTTP and HTTPS traffic to all virtual machines in a project, the following command creates a firewall that allows incoming HTTP and HTTPS requests from anywhere to any instance connected to this network.

$ gcloud compute firewall-rules create FIREWALL_RULE --allow tcp:80,tcp:443


$ gcloud compute firewall-rules create sample-http \
                 --description "Incoming http and https allowed." \
                 --allow tcp:80,tcp:443
$ gcloud compute firewall-rules describe sample-http
- IPProtocol: tcp
  - '80'
  - '443'
creationTimestamp: '2014-06-13T13:27:12.206-07:00'
id: '5057780722612413546'
kind: compute#firewall
name: sample-http
network: https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default
selfLink: https://www.googleapis.com/compute/v1/projects/myproject/global/firewalls/samplehttp
Developers Console

You can use the Developers Console to create an overall firewall rule for all instances on the network, or you can allow individual instances access to HTTP and HTTPS connections by selecting the respective option when you create that instance. The latter option is described first, because it provides more control over individual instances.

  1. Go to the Google Developers Console.
  2. Select your Compute Engine project.
  3. In the sidebar on the left, click VM instances.
  4. Click Create instance.
  5. In the options for creating a new instance, select the appropriate checkboxes for HTTP and HTTPS traffic (Allow HTTP, Allow HTTPS, or both).
  6. Create your instance.

By selecting these checkboxes, Compute Engine automatically creates a default-http or default-https rule that applies to all instances with either the http-server or https-server tags. Your new instance is also tagged with the appropriate tag depending your checkbox selection.

If you already have existing default-http and default-https firewall rules, you can apply the firewall rule to existing instances by enabling the Allow HTTP or Allow HTTPS options on the instance's details page.

  1. Go to the Google Developers Console.
  2. Select your Compute Engine project.
  3. In the sidebar on the left, click VM instances.
  4. Click on the name of the desired instance.
  5. Click Edit button at the top of the page.
  6. Scroll down to the Firewalls section.
  7. Check the Allow HTTP or Allow HTTPS options under your desired network.
  8. Click Save.

In a similar manner, you can also disable external HTTP or HTTPS access for an instance by unchecking one or both checkboxes.

By allowing specific instances to be tagged for HTTP and HTTPS traffic rather than creating an overall firewall rule that applies to all instances, Compute Engine limits the possible security implications of allowing external traffic to all virtual machines in a project. However, if you would like to create a firewall rule that allows HTTP or HTTPS traffic to all virtual machine instances, you can create your own firewall rule:

  1. Go to the Google Developers Console.
  2. Select your Compute Engine project.
  3. In the sidebar on the left, click on Networks.
  4. Select the network where you would to apply the firewall rule.
  5. Click Create new next to Firewall rules.
  6. Name your firewall rule, and add tcp:80 in the Protocols & Ports box, or tcp:443 for HTTPS traffic.
  7. Click Create.

Advanced networking details

This section provides some low-level details not covered in the previous sections. You do not need to read this for typical usage, but it provides more insight about how networking works in Compute Engine. The following diagram describes these low-level details, with more information in the corresponding sections.

A more detailed diagram of the Compute Engine


  • Stores a lookup table that tracks every active connection. When a packet arrives that is part of an active connection, it will be sent to the destination without consulting any firewall rules.
  • Stores a lookup table that associates external IP addresses with instances. All packets to the external IP are routed to the network, which looks up the internal IP corresponding to that address, and forwards it to the instance.
  • Performs MAC address lookups (proxy ARP) for a given IP address.
  • Routes packets to and from instances on the network.
  • Routes packets externally (billing involved).


  • Compute Engine uses a firewall that can block packets into an instance; it cannot block packets from leaving an instance. If you want to block outgoing packets from an instance, you must configure another technology, such as iptables, on your instances.
  • Once a connection has been made, all incoming and outgoing packets with the same two IP addresses, same instance port, and same protocol will be permitted until the connection expires, which it will do after about 10 minutes of inactivity. However, if a reply is sent to a different instance port (for example if an FTP request asks for a response from another port), the response is not automatically allowed; there must be a firewall rule permitting a connection on the new port.


  • Each instance's metadata server also acts as a DNS resolver for that instance. DNS lookups are performed for instance names. The metadata server itself stores all DNS information for the local network and queries Google's public DNS servers for any addresses outside of the local network.
  • An instance is not aware of any external IP address assigned to it. Instead, the network stores a lookup table that matches external IP addresses with the internal IP addresses of the relevant instances.

Who Handles What

Under the hood, different networking features are handled by different parts of the Compute Engine system. Some of these are standard networking features that are well documented, and some of them are specific to Compute Engine. Some features you can configure, and some you cannot. Compute Engine uses Linux's VIRTIO network module to model Ethernet card and router functionality, but higher levels of the networking stack, such as ARP lookups, are handled using standard networking software.

ARP lookup
The instance kernel issues ARP requests and the Network issues ARP replies. The mapping between MAC addresses and IP addresses is handled by the instance kernel.
MAC lookup table, IP lookup table, active connection table
These tables are hosted on the underlying network and cannot be inspected or configured.
DNS server
Each instance's metadata server acts as a DNS server. It stores the DNS entries for all network IP addresses in the local network and calls Google's public DNS server for entries outside the network. You cannot configure this DNS server, but you can set up your own DNS server if you like and configure your instances to use that server instead by editing the /etc/resolv.conf file.
Packet handling between the network and the outside
Packets coming into or out of the network are handled by network code that examines the packet against firewall rules, against the external IP lookup table, and against the active connections table. The network also performs NAT on packets coming into and out of the network.
Packets received by an instance
These packets are received and turned into a stream by the instance kernel in the standard fashion.
Packets sent by an instance
Packets are sent by the instance kernel in the standard way. Interface and network functionality are modeled using the VIRTIO network module.

Detailed connection walkthroughs

Here are more details about what happens when an instance makes a network call.

An instance makes a call:

  1. If the target address is an instance name or a URL such as www.google.com, the instance calls the DNS service on its metadata server and gets back the matching IP address. You can configure your instance to consult another DNS service, although then you will not be able to resolve instance names.
  2. The destination IP address is examined against the network's IP address range, which every instance knows.

    1. If the IP address is outside the network IP range:

      1. The instance sends the packet to the network's gateway MAC address with the destination set to the packet's final destination. The instance might need to make an ARP request to resolve the gateway's MAC address.

      2. The network receives the packet and rewrites the IP header to declare the instance's external IP address as the source. If the instance has no external IP address, the call is not allowed, and the network drops the packet without informing the sender.

      3. The network records the outgoing packet and adds the source and destination to the active connections table.

      4. The network sends the packet on to its destination.

      5. The destination gets the packet and responds if it chooses.

      6. The network receives the response, consults the active connections table, notes that this is an active connection, and allows it. The network consults its network/external IP lookup table and replaces the instance's external IP address with the matching network address and sends the packet to the source instance.

      7. The instance receives the packet.

    2. If the destination IP address is within the network IP range:

      1. The instance makes a standard ARP request to the network to learn the matching MAC address for this IP, unless it has cached the MAC address for this IP as part of a previous request.

      2. The network, using Proxy ARP, responds with the MAC address of the destination instance.

      3. The instance sends the packet to the network with the target MAC and IP address set to the destination instance.

      4. The network checks for a firewall rule that permits a connection to this target: if so, it sends it on; if not, it simply drops the packet without informing the sender.

      5. If the packet is allowed, the network records or updates the status of this connection in a table of active connections.

      6. The target instance gets the packet. If appropriate, it sends a reply to the network addressed to the source instance. If the MAC address is not cached, it performs a standard ARP request similar to that done by the source.

      7. The network consults the active connection table, sees that the reply is part of active connection, and routes it on to the destination. If the reply had been over a different port, the reply would not match a known connection and the network would again examine the firewall for a rule allowing the connection. If an allowing firewall rule existed, the network would log the connection and send the reply to the source. An example of when this might occur is an FTP request that specified a different reply port.

      8. The source instance receives the reply.

An external instance or computer calls an instance:

  1. The external caller sends a packet to an instance's external IP address, which is owned by the network.

  2. The network compares the packet against the active connections table to see whether this is an existing connection:

    1. If it is not an existing connection, then the network looks for a firewall rule to allow the connection.
    2. If there is no firewall rule, the network drops the packet without informing the sender.
  3. If there is an existing connection or valid firewall, the network examines its lookup table and replaces the external IP with the corresponding network IP in the packet, logs the incoming packet in the active connections table, and sends the packet to the target instance.

  4. The instance receives the packet and responds as described in If the IP address is outside the network IP range above when sending a packet outside the network range.

  5. The network receives the reply, finds the matching incoming request in the active connections table, and allows the packet through. Before sending, it modifies the source IP address by replacing the instance's network IP with the corresponding external IP from its lookup table.


A firewall has rules that define what incoming connections are accepted by which instances. Each rule specifies a permitted incoming connection request, defined by source, destination, ports, and protocol. When a request is sent to an instance, whether internally or from another network or the Internet, Compute Engine allows the request if any rule in the firewall permits the connection.

The firewall does not restrict an instance from sending a packet to another instance in the same network. Any instance can send packets to any other instance in its network. However, whether that packet is accepted is determined by the firewall rules associated with the target instance. To regulate outgoing requests, use another system, such as iptables.

Only instances with an external IP address can send packets outside the network. Only instances with an external IP address and a permitting firewall rule can be addressed directly from outside the network. Alternatively, you can route packets to instances without external IP address via an externally addressable proxy server.

You cannot share firewall rules between projects or between networks in the same project.

Compute Engine uses a connection tracking table to support stateful firewall filtering. The maximum number of connections in the table depends on the instance type. Current maximum connections are as follows:

  • 130000 per instance for instances with <1 CPU
  • 130000 per CPU for instances with 1 to 8 CPUs
  • 130000*8 (1040000) per instance for instances with >8 CPUs.

Once the active connections exceed the limit, the firewall becomes stateless for new connections.

A firewall rule exposes the following properties, which can also be set using the gcloud compute firewall-rules create command. Each rule is composed of several elements, most of which must be defined before a connection is allowed:

[Required] The network that this firewall rule is assigned with. Each firewall rule can be associated with one and only one network. You must provide a network when making an API call to create a firewall rule. However, if you use gcloud compute and do not specify a network, the rule will automatically be assigned to the default network.

[Required if sourceTags is not specified] Identifies permitted callers by a list of IP address blocks expressed in CIDR notation. If neither sourceRanges nor sourceTags are specified, the default is, which means that the rule applies to all incoming connections from inside or outside the network. For example:

"sourceRanges": [ "", "" ]

[Required if sourceRanges is not specified] If the source is within the network and is associated with one of the specified tags, the connection will be accepted. If both sourceRanges and sourceTags are specified, an inbound connection is allowed if either the range or the tag of the source matches sourceRanges or sourceTags. For example:

"sourceTags": [ "management" ]

[Optional] A list of instance tags that specify which instances on the network can accept requests from the specified sources. If not specified, this firewall rule applies to all instances on this network. For example:

"targetTags": [ "web", "database" ]

[Required] An array of allowed connections permitted by this firewall rule. Each contains an IP protocol and an optional range of ports (for TCP and UDP traffic) that should be allowed to reach the instances specified by targetTags.

[Required] The protocols allowed over this connection. This can be the (case-sensitive) string values tcp, udp, icmp, esp, ah, sctp, or any IP protocol number.
[Optional] An array of target ports allowed for this connection. This is only applicable for TCP and UDP connections. Each value is a string that is either a single port or a port range. If not specified, all ports are allowed. Example: ["80", "160", "300-500"]

For example:

"allowed": [
    "IPProtocol": "tcp",
    "ports": [ "22" ],
    "IPProtocol": "udp",
    "ports": [ "161" ],

[Required] The firewall name. The name must be unique in this project, from 1-63 characters long and match the regular expression: [a-z]([-a-z0-9]*[a-z0-9])? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.

The default network in any project starts with the following standard firewall rules. You can modify or delete these rules, and you can add, modify, and delete additional rules.

Allows network connections of any protocol and port between any two instances.
Allows TCP connections from any external or internal source to any instance on the network over port 22. Instances without external IP addresses will still not be directly reachable from external sources.
Allows ICMP traffic from any source to any instance on the network.
Allows remote desktop protocol traffic to port 3389.

The default rules above do not allow HTTP or HTTPS traffic from external sources. Setting Up an External HTTP Connection has instructions for allowing such traffic.


The following example describes the default-allow-ssh firewall rule. The source CIDR of means that the connection can come from anywhere, inside or outside of the network.

$ gcloud compute firewall-rules describe default-allow-ssh
- IPProtocol: tcp
  - '22'
creationTimestamp: '2014-07-08T10:32:46.214-07:00'
description: Allow SSH from anywhere
id: '13715544083725015625'
kind: compute#firewall
name: default-allow-ssh
network: https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default
selfLink: https://www.googleapis.com/compute/v1/projects/myproject/global/firewalls/default-allow-ssh

Useful gcloud compute commands:

Add a firewall rule

To add a firewall rule, create a Firewall rule resource describing the permitted IP ranges, target tags, target ports, source tags, protocol, and network. Any instance connected to the specified network will have that firewall applied. In gcloud compute, use the firewall-rules create command:

$ gcloud compute firewall-rules create FIREWALL_RULE \
    [--network NETWORK; default="default"] \
    [--source-ranges CIDR_RANGE,[CIDR_RANGE,…]]


The following example adds a firewall that supports HTTP connections over port 80 from any source to any instance in the network that exposes an external IP address.

$ gcloud compute firewall-rules create allow-http --description "Incoming http allowed." \
         --allow tcp:80 --format json

  "allowed": [
      "IPProtocol": "tcp",
      "ports": [
  "creationTimestamp": "1234-56-78T09:12:34.567",
  "description": "Incoming http allowed.",
  "id": "13AAA70BBBB5639CCCC9",
  "kind": "compute#firewall",
  "name": "allow-http",
  "network": "https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default",
  "selfLink": "https://www.googleapis.com/compute/v1/projects/myproject/global/firewalls/allowhttp",
  "sourceRanges": [

Delete a firewall rule

To delete a firewall rule, run the firewall-rules delete command:

$ gcloud compute firewall-rules delete FIREWALL_RULE

Routes collection

Every project has a Routes collection that determines how packets leaving an instance should be handled. The Routes collection contains all routes for that project and each route is a single rule that specifies which network should handle a packet leaving a virtual machine instance. For example, a route may specify that packets leaving any instances in the network whose destination range matches should be routed to another virtual machine instance before it can be sent on to its final destination.

By default, every network has two default routes: a route that directs traffic to the Internet and a route that directs traffic to other instances within the network. These default routes are generally sufficient for most projects.

Routes allow you to implement more advanced networking functions in your virtual machines, such as setting up many-to-one NAT and transparent proxies. If you do not need any advanced routing solutions, the default routes should be sufficient for handling most outgoing traffic.

Instance routing tables

Each route in the Routes collection may apply to one or more instances. A route applies to an instance if the network and instance tags match. If the network matches and there are no instance tags specified, the route applies to all instances in that network. Compute Engine then uses the Routes collection to create individual read-only routing tables for each instance.

A good way to visualize this is to imagine a massively scalable virtual router at the core of each network. Every virtual machine instance in the network is directly connected to this router, and all packets leaving a virtual machine instance are first handled at this layer before they are forwarded on to their next hop. The virtual network router selects the next hop for a packet by consulting the routing table for that instance. The diagram below describes this relationship, where the green boxes are virtual machine instances, the router is at the center, and the individual routing tables are indicated by the tan boxes.

The Routes collection for the network in the diagram might look like this:

NAME                           NETWORK DEST_RANGE    NEXT_HOP                 PRIORITY
default-route-68079898SAMPLEe7 default     default-internet-gateway   1000
default-route-78SAMPLEd2bc5762 default                            1000
vpngateway                     default us-central1-a/instances/vpngateway  1000

A closer look at the vpngateway route exposes the vpn tag on the route:

$ gcloud compute routes describe vpngateway
creationTimestamp: '2014-07-28T15:26:27.023-07:00'
id: '12304245498973864442'
kind: compute#route
name: vpngateway
network: https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default
nextHopGateway: https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/vpngateway
priority: 1000
selfLink: https://www.googleapis.com/compute/v1/projects/myproject/global/routes/vpngateway
- vpn

The vpngateway route ensures that any instance with the vpn tag automatically has a routing table that contains the vpngateway route alongside the two default routes. In the diagram, both vm1 and vm2 have these routes in their routing table, so all outgoing traffic destined for the external IP range is handled by the vpngateway instance.

An instance's routing table is a read-only entity. You cannot directly edit these tables. If you want to add, remove, or edit a route, you must do so through the Routes collection.

Individual routes

A single route is made up of the following:

[Required] The user-friendly name for this route. For example, internetroute for a route that allows access to the Internet.
[Required] The name of the network this route applies to. For example, the default network.
[Required] The destination IP range that this route applies to. If the destination IP of a packet falls in this range, it matches this route. For example, See the Route Selection section to understand how Compute Engine uses all matching routes to select a single next hop for a packet.
[Required] The list of instance tags this route applies to. If this is empty, this route applies to all instances within the specified network. In the API, this is a required field. In gcloud compute, this is an optional field and gcloud compute assumes an empty list if this field is not specified.

Exactly one of the following next hop specifications is required:


The fully-qualified URL of the instance that should handle matching packets. The instance must already exist and have IP forwarding enabled. For example:


If a next hop instance crashes and is restarted by the system, or if you delete an instance and recreate it with the same name in the same zone, Compute Engine will continue to route matching packets to the new instance.


The network IP address of an instance that should handle matching packets. The IP address must lie within the address space of the network. For example, if your network is, you cannot specify nextHopIp= The instance must already exist and have IP forwarding enabled. If the next hop instance crashes and is later restarted by the system with the same IP address or if the user deletes the instance and recreates it with the same IP address, Google Compute Engine continues routing matching packets to the new instance.


[Read-Only] The URL of the local network handling matching packets. This is only available to the default local route. You cannot manually set this field.


The URL of a gateway that should handle matching packets. Currently, there is only the Internet gateway available:


The URL of a Compute Engine VPN tunnel that should handle matching packets.


[Required] The priority of this route. Priority is used to break ties in the case where there is more than one matching route of maximum length. A lower value is higher priority; a priority of 100 has higher priority than 200. For example, the following routes are tied because they have the same prefix length and they are in the same network. The differing priority breaks the tie so that vpnroute wins.

NAME                       NETWORK     DEST_RANGE         NEXT_HOP                            PRIORITY
vpnroute                   default     ZONE/instances/vpninstance          1000
vpnroute-backup            default     ZONE/instances/vpninstance-backup   2000

Under this configuration, VPN traffic would normally be handled by vpninstance, but would fall back to vpninstance-backup if vpnroute is deleted.

In the API, this is a required field. In gcloud compute, this is an optional field and gcloud compute assumes a default priority of 1000 if the field is not specified.

Default routes

By default, every network you create comes with two routes in the Routes collection:

  • A local route that handles packets destined within the network.
  • An Internet route that sends all other packets to the Internet gateway.

These default routes are assigned unique names generated by the server and can look similar to the following:

NAME                           NETWORK DEST_RANGE    NEXT_HOP                 PRIORITY
default-route-17937a9d507c5897 default     default-internet-gateway 1000
default-route-1949ae767c041c44 default                          1000

The Internet route is identifiable by the next hop default-internet-gateway, while the local route is identifiable by the fact that the NEXT_HOP field is blank and the DEST_RANGE is the same as the whole network range. You can choose to edit or delete the default Internet route for a network, but you cannot delete the local route. It is also not possible to create routes that override the local route with a more specific route. For example, if your network IP space is, you can create a route with a destination range of because it is less specific than the local route and therefore doesn't override it. However, you cannot create routes that are as specific or more specific than the local route, such as a route with a destination range of

If you have multiple networks in your project, there will also be multiple sets of default routes:

NAME                           NETWORK   DEST_RANGE       NEXT_HOP                 PRIORITY
default-route-17937a9d507c5897 default     default-internet-gateway 1000
default-route-1949ae767c041c44 default                          1000
default-route-6d248c6dcd28c489 network-2     default-internet-gateway 1000
default-route-957c297a50eb5b7e network-2                          1000

The example above shows two sets of default routes. Each set applies to a different network. For example, the first two routes apply to the default network default, and the last two routes apply to the network-2 network. The Routes collection lists all routes that apply to your project, so it is possible to see multiple routes with similar criteria, such as the same destination range and next hop, that apply to different networks.

Route selection

When an outgoing packet leaves a virtual machine instance, Compute Engine uses the following steps to decide which route to use and where to forward the packet:

  1. Compute Engine discards all but the most specific routes that match the packet’s destination address. For example, if destinationRange= and there is a route for and a route for, Compute Engine selects the route because it is more specific.

  2. If there are multiple routes with the same prefix length, Compute Engine discards all routes except the ones with the smallest priority value (smallest priority value indicates highest priority). There may still be more than one route left at this point.

  3. Compute Engine computes a hash value of the IP protocol field, the source and destination IP addresses, and the source and destination ports. Compute Engine uses this hash value to select a single next hop from the remaining ties.

  4. If a next hop is found, Compute Engine forwards the packet. If a next hop is not found, the packet is dropped and Compute Engine replies with an ICMP destination or network unreachable error.

It is important to note that Compute Engine does not consider network distance when selecting a next hop. The next hop instance or gateway could be in a different zone than the instance sending the packet, so you should engineer your routing tables to control locality. For example, you can use instance tags to direct packets for instances in different zones to prefer a local transparent proxy or VPN gateway. By tagging instances by zone, you can ensure that packets leaving an instance in one zone will only be sent to a next hop in the same zone.

List routes

To see a list of routes for a project using gcloud compute, run the routes list command:

$ gcloud compute routes list

For example:

$ gcloud compute routes list
NAME                           NETWORK   DEST_RANGE    NEXT_HOP                 PRIORITY
default-route-17937a9d507c5897 default     default-internet-gateway 1000
default-route-1949ae767c041c44 default                          1000
default-route-6d248c6dcd28c489 network-2     default-internet-gateway 1000
default-route-957c297a50eb5b7e network-2                          1000

Add a route

To add a route to the routing table using gcloud compute, use the routes create command:

$ gcloud compute routes create ROUTE --destination-range DEST_RANGE --network NETWORK NEXT_HOP

To add a route through the RESTful API, construct a HTTP POST request to the following URI:


Your request body must be constructed similar to the following, replacing nextHopGateway with your desired next hop:

{ "name": "mynewroute",
  "description": "new,
  "tags": [],
  "destRange": "",
  "priority": 1000,
  "nextHopGateway": "https://www.googleapis.com/compute/v1/projects/myproject/global/gateway/default-internet-gateway",
  "network": "https://www.googleapis.com/compute/v1/projects/myproject/global/networks/<network-name>"

Delete a route

To delete a route, run the routes delete command:

$ gcloud compute routes delete ROUTE

To delete a route in the API, make a HTTP DELETE request to the following URI, with an empty request body:


Consistency of route operations

When you make changes to the Routes collection, these changes are eventually consistent across all instances. This means that after you update, add, or remove a route, the changes are only guaranteed to have taken affect on all applicable instances once your operation returns a status of DONE. A PENDING or RUNNING operation means that the change may have taken effect on some instances but has not taken effect on all instances.

If you make a sequence of changes, these changes may be applied to your instances in any order. There is no guarantee that the order in which you make your requests will be the order in which these requests are processed. Since routing changes do not take affect instantaneously, different instances may observe different changes at different times. However, your operation will move to a DONE state once the changes have been implemented on all affected instances.

Enable IP forwarding for instances

By default, Compute Engine instances are blocked from sending packets whose source IP address does not match the IP address of the instance sending the packet. Similarly, Compute Engine won't deliver a packet whose destination IP address is different than the IP address of the instance receiving the packet. However, both capabilities are required if you want to use instances to help route packets. To disable this source and destination IP check, enable the canIpForward field, which allows an instance to send and receive packets with non-matching destination or source IPs.

To set the canIpForward field in gcloud compute, use the --can-ip-forward flag when creating your instance:

$ gcloud compute instances create ... --can-ip-forward

In the API, set the canIpForward field to true when you construct the request body to create a new instance:

  "name": "myinstance",
  "description": "",
  "image": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD",
  "machineType": "https://www.googleapis.com/compute/v1/projects/myproject/global/machineTypes/n1-standard-2",
  "networkInterfaces": [
  "canIpForward": true

You can only set this field at instance creation time. After an instance is created, the field becomes read-only.

Interacting with firewall rules

Just creating a route does not ensure that your packets will be received by the specified next hop. Firewall rules still determine whether incoming traffic is allowed into a network or instance. For example, if you create a route that sends packets through multiple instances, each instance must have an associated firewall rule to accept packets from the previous instance.

For IP address matching, only the source IP address of the packet is used, which is not necessarily the IP address of the instance sending the packet. If you have a firewall rule that specifies only packets from are accepted, all packets with that source IP address are accepted, regardless of the IP address of the instance that sent the packets.

  • If instance has canIpForward enabled and spoofs a packet to have source IP, the firewall will reject the packet.
  • If instance has canIpForward enabled and spoofs a packet to have source IP, the firewall will accept the packet.

A target tag is an alias for the IPs of the instances that will receive the packet. Source tags are aliases for the source IPs of packets, not the IPs of the instances sending the packets. For example, if a tag named mytag is assigned to an instance with IP, a rule that allows traffic from mytag would allow any packets with a source IP of, regardless of which instance sends the packet. This is important because an instance with IP forwarding enabled can send a packet with a source IP address different from the instance IP address.

In the future, Compute Engine may change the way firewall rules handle source tags.

For more information, see Firewalls.

Routing packets to the Internet

Currently, any packets sent to the Internet must be sent by an instance that has an external IP address. If you create a route that sends packets to the Internet from a particular instance, that instance must also have an external IP. If you create a route that sends packets to the Internet gateway, but the source instance doesn't have an external IP address, the packet will be dropped.

Configure a NAT gateway

You can create more complicated networking scenarios by making changes to the Routes collection. This section describes how you can set up a network address translation (NAT) gateway instance that can route traffic from internal-only virtual machine instances to the Internet. This allows you to use one external IP address to send traffic from multiple virtual machine instances but only expose a single virtual machine to the Internet.

  1. To start, create a Compute Engine network to host your virtual machine instances for this scenario. In this example, the network range used is with a gateway of However, you can select your own IPv4 range and gateway address as well.

    $ gcloud compute networks create gce-network --range
  2. Create firewall rules to allow ssh connections in the new network you just created.

    $ gcloud compute firewall-rules create gce-network-allow-ssh --allow tcp:22 --network gce-network
    $ gcloud compute firewall-rules create gce-network-allow-internal --allow tcp:1-65535,udp:1-65535,icmp \
             --source-ranges --network gce-network
  3. Create a virtual machine to act as a NAT gateway on gce-network or the default network.

    $ gcloud compute instances create nat-gateway --network gce-network --can-ip-forward \
             --zone us-central1-a \
             --image debian-7 \
             --tags nat
  4. Tag any virtual machine instances without an external IP address that will use the gateway instance with the tag no-ip, or create a new virtual machine without an external IP address and tag the instance with the no-ip tag.

    # Add tags to an existing instance ...
    $ gcloud compute instances add-tags existing-instance --tags no-ip
    # Or create a new virtual machine without an external IP address
    $ gcloud compute instances create example-instance --network gce-network --no-address \
             --zone us-central1-a --image debian-7 --tags no-ip
  5. Create a route to send traffic destined to the Internet through your gateway instance.

    $ gcloud compute routes create no-ip-internet-route --network gce-network \
             --destination-range \
             --next-hop-instance nat-gateway \
             --next-hop-instance-zone us-central1-a \
             --tags no-ip --priority 800

    Setting the priority of this route ensures that this route wins if there are any other conflicting routes. 1000 is the default priority and a value lower than 1000 will take precedent.

  6. Next, log onto your gateway instance and configure iptables to NAT internal traffic to the Internet.

    $ gcloud compute ssh nat-gateway --zone us-central1-a

    On your instance, configure iptables:

    user@nat-gateway:~$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
    user@nat-gateway:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

    The first sudo command tells the kernel that you want to allow IP forwarding. The second sudo command masquades packets received from internal instances as if they were sent from the NAT gateway instance.

Set up a VPN gateway

This section describes installing Strongswan VPN software on one of your instances. For Compute Engine VPN, see Cloud VPN.

This section describes an example scenario that connects a VPN gateway instance in Compute Engine to a Debian-based VPN gateway in your non-Cloud network. This scenario is just an example and may or may not be suitable for your network. Consult with your network administrator for more information.

  1. To start, create a Compute Engine network to connect via VPN.

    $ gcloud compute networks create gce-network --range
  2. Create a VPN gateway virtual machine on gce-network.

    $ gcloud compute instances create vpn-gateway --can-ip-forward \
             --network gce-network \
             --zone us-central1-a \
             --image debian-7 \
             --tags vpn
  3. Make note of your newly created virtual machine's internal IP address by running the following command:

    $ gcloud compute instances describe --zone us-central1-a vpn-gateway

    Note the address next to networkIP (not natIP). It should begin with 10.120.x.x.

  4. Create a "plain old" non-VPN gateway virtual machine to talk to your local network.

    $ gcloud compute instances create povm-1 --network gce-network --image debian-7 --tags vpn --zone us-central1-a
  5. Create a route in gce-network to route traffic through vpn-gateway if it is destined for your local network.

    $ gcloud compute routes create gce-network-via-gateway --destination-range LOCAL_NETWORK_ADDRESS_SPACE \
             --next-hop-address VPN_GATEWAY_NETWORK_IP \
             --network gce-network \
             --tags vpn

    The VPN_GATEWAY_NETWORK_IP value should be the networkIp that you noted from step 3.

  6. Add the following Compute Engine firewall rules for your Compute Engine network to accept incoming traffic.

    $ gcloud compute firewall-rules create ssh --source-ranges --allow tcp:22 --network gce-network
    $ gcloud compute firewall-rules create  allow-internal --source-ranges --allow tcp:1-65535,udp:1-65535,icmp \
             --network gce-network --target-tags vpn
    $ gcloud compute firewall-rules create allow-ipsec-nat --source-ranges IP_LOCAL_VPN_GATEWAY/32 \
             --allow udp:4500,udp:500 --network gce-network --target-tags vpn
    $ gcloud compute firewall-rules create allow-all-peer --source-ranges LOCAL_NETWORK_ADDRESS_SPACE \
             --allow tcp:1-65535,udp:1-65535,icmp --network gce-network --target-tags vpn

    You might also need to set up firewall settings in your local network to accept incoming traffic from the Compute Engine network. Depending on your network, this process can vary.

  7. Install VPN software and configure gateway guest OS. You will need your VPN gateway machine's external IP address. Run the following command:

    $ gcloud compute instances describe vpn-gateway

    Copy the external IP address and create a file named ipsec.conf on your virtual machine gateway instance. Populate it with the following contents:

    conn myconn

    Your <internal-ip-subnet> value should be either or, based on the internal-ip value that you noted in step 3.

    Then, run the following commands, replacing <secret-key> with a secret key you choose:

    $ sudo apt-get update
    $ sudo apt-get install strongswan -y
    $ echo "%any : PSK \"<secret-key>\"" | sudo tee /etc/ipsec.secrets > /dev/null
    $ sudo sysctl -w net.ipv4.ip_forward=1
    $ sudo cp ipsec.conf /etc
    $ sudo ipsec restart
    $ sudo ipsec up myconn

    Assuming your local gateway machine is running a Debian-based operating system, you can use the same steps to install VPN on your local machine. Make a copy of your ipsec.conf file with the following changes on your local gateway machine:

    conn myconn

    Run the same commands described above on your local VPN gateway machine.

  8. Try it out:

    $ gcloud compute ssh povm-1 --command 'ping -c 3 LOCAL_NETWORK_EXTERNAL_ADDRESS'


If you are experiencing issues with your VPN setup based on the instructions above, try these tips to troubleshoot your setup:

  1. Determine whether the two VPN endpoints are able to communicate at all.

    Use netcat to send VPN-like traffic (UDP, port 4500). Run the following command on your local VPN endpoint:

    $ echo | nc -u <vpn-vm-gateway-external-address> 4500

    Run tcpdump on the receiving end to determine that your Compute Engine instance can receive the packet on port 4500:

    $ tcpdump -nn -n host <public-ip-of-local-VPN-gateway-machine> -i any
  2. Turn on more verbose logging by adding the following lines to your ipsec.conf files:

    config setup
      charondebug="ike 3, mgr 3, chd 3, net 3"
    conn myconn

    Next, retry your connection. Although the connection should still fail, you can check the log for errors. The log file should be located at /var/log/charon.log on your Compute Engine instance.