Page last updated:
This topic describes how Gorouter, the main component in Cloud Foundry’s routing tier, routes HTTP traffic within Cloud Foundry (CF).
HTTP traffic passed from Gorouter to an app includes the following HTTP headers:
X-Forwarded-Protogives the scheme of the HTTP request from the client. The scheme is HTTP if the client made an insecure request or HTTPS if the client made a secure request. Developers can configure their apps to reject insecure requests by inspecting the HTTP headers of incoming traffic and rejecting traffic that includes
X-Forwarded-Protowith the scheme of HTTP.
X-Forwarded-Forgives the IP address of the client originating the request.
If your load balancer terminates TLS on the client side of Gorouter, it must append these headers to requests forwarded to Gorouter.
Zipkin is a tracing system that enables app developers to troubleshoot failures or latency issues. Zipkin provides the ability to trace requests and responses across distributed systems. See Zipkin.io for more information.
The Gorouter examines the HTTP request headers and performs the following:
- If the
X-B3-SpanIdHTTP headers are not present in the request, Gorouter generates values for these and inserts the headers into the request forwarded to an application. These values are also found in Gorouter access log message for the request:
- If both
X-B3-SpanIdHTTP headers are present in the request, Gorouter forwards the same value for
X-B3-TraceId, generates a new value for
X-B3-SpanId, and adds the
X-B3-ParentSpanheader, and sets to the value of the span id in the request. In addition to these trace and span ids, Gorouter access log message for the request includes
Developers can then add Zipkin trace IDs to their application logging in order to trace app requests and responses in Cloud Foundry.
After adding Zipkin HTTP headers to app logs, developers can use
cf logs myapp to correlate the trace and span ids logged by Gorouter with the trace ids logged by their app. To correlate trace IDs for a request through multiple apps, each app must forward appropriate values for the headers with requests to other applications.
Developers who want to obtain debug data for a specific instance of an app can use the HTTP header
X-CF-APP-INSTANCE to make a request to an app instance.
Perform the following steps to make an HTTP request to a specific app instance:
- Obtain the GUID of your app:
$ cf app YOUR-APP --guid
- List your app instances and retrieve the index number of the instance you want to debug:
$ cf app YOUR-APP
- Make a request to the app route using the HTTP header
X-CF-APP-INSTANCEset to the concatenated values of the app GUID and the instance index:
$ curl app.example.com -H "X-CF-APP-INSTANCE":"YOUR-APP-GUID:YOUR-INSTANCE-INDEX"
Applications that require mutual TLS (mTLS) need metadata from client certificates to authorize requests. Cloud Foundry supports this use case without bypassing layer-7 load balancers and Gorouter.
The HTTP header
X-Forwarded-Client-Cert (XFCC) may be used to pass the originating client certificate along the data path to the application. Each component in the data path must trust that the back-end component has not allowed the header to be tampered with.
If you configure the load balancer to terminate TLS and set the XFCC header from the received client certificate, then you must also configure the load balancer to strip this header if it is present in client requests. This configuration is required to prevent spoofing of the client certificate.
The following sections describe supported deployment configurations.
By default, Gorouter forwards arbitrary headers that are not otherwise mentioned in the docs; this includes the XFCC header.
For applications to receive the XFCC header, configure your load balancer to set the XFCC header with the contents of the client certificate received in the TLS handshake.
This mode is enabled when the TLS terminated for the first time at infrastructure load balancer option is selected in the Networking configuration screen of the PAS tile.
This option allows you to configure support for the XFCC header while leveraging HAProxy. When selected, HAProxy sets the XFCC header to the contents of the client certificate received in the TLS handshake.
Selecting this configuration requires that the load balancer in front of HAProxy is configured to pass through the TLS handshake to HAProxy via TCP.
This mode is enabled when the TLS terminated for the first time at HAProxy option is selected in the Networking configuration screen of the PAS tile.
HAProxy trusts the Diego intermediate certificate authority. This trust is enabled automatically and permits mutual authentication between applications that are running on Pivotal Cloud Foundry.
If the Gorouter is the first component to terminate TLS, such that it receives the certificate of the originating client in the mutual TLS handshake, the operator should select this option. When selected, Gorouter sets the XFCC header to the contents of the client certificate received in the TLS handshake and strips the XFCC header when present in a request.
Selecting this configuration requires that the load balancer in front of Gorouter is configured to pass through TLS handshake to Gorouter via TCP.
This mode is enabled when the TLS terminated for the first time at the Router option is selected in the Networking configuration screen of the PAS tile.
Gorouter trusts the Diego intermediate certificate authority. This trust is enabled automatically and permits mutual authentication between applications that are running on Pivotal Cloud Foundry.
Depending on your needs, you can configure your deployment to terminate TLS at Gorouter, at Gorouter and the load balancer, or at the load balancer only.
Gorouter supports TLS and mutual authentication to back-end destinations, including app instances, platform services, and any other routable endpoints.
This is enabled by configuring the following manifest properties:
router.ca_certs: must include the CA certificate used to sign any back end to which Gorouter initiates a TLS handshake.
Gorouter does not automatically initiate TLS handshakes with back-end destinations. To register that Gorouter must initiate a TLS handshake before forwarding HTTP requests to a component, the component must include the following optional fields in its
route.register message to NATS:
"tls_port": The port to which Gorouter should open a connection and initiate a TLS handshake
"server_cert_domain_san": An identifier for the back end which Gorouter expects to find in the Domain Subject Alternative Name of the certificate presented by the back end. This is used to prevent misrouting for back ends whose IPs and/or ports are expected to change; see Consistency.
To enable TLS from Gorouter to application instances, some additional configuration is required in addition to the properties above; see Configuring Consistency with TLS.
Authors of routable components can configure Route Registrar to send the necessary NATS message automatically.
To enable mutual authentication between Gorouter and back ends, operators configure Gorouter with a certificate and private key using the following manifest properties:
Gorouter presents the certificate if requested by the back end during the TLS handshake.
As CF manages and balances apps, the internal IP address and ports for app instances change. To keep Gorouter’s routing tables current, a Route Emitter on each Diego cell sends a periodic update to all Gorouters through NATS, reminding them of the location of all app instances; the default frequency of these updates is 20 seconds. Gorouter tracks a time-to-live (TTL) for each route to back-end mapping; this TTL defaults to 120 seconds and is reset when Gorouter receives an updated registration message.
Network partitions or NATS failures can cause Gorouter’s routing table to fall out of sync, as CF continues to re-create containers across hosts to keep apps running. This can lead to routing of requests to incorrect destinations.
You can configure Gorouter to handle this problem in two ways:
|Consistency mode||Security of traffic between Gorouter and Containers||Gorouter Route Pruning|
|With TLS Enabled||Encrypted via TLS||Routes are pruned on failure of TLS handshake only. See Gorouter TLS pruning behavior.|
|Without TLS Enabled||Plain text||Routes are pruned on TTL expiry|
Both of these consistency modes are described below.
This consistency mode is newer and has the following benefits:
- Improved availability for applications by keeping routes in Gorouters routing table when TTL expires
- Increased guarantees against misrouting, by validating the identity of back ends before forwarding requests
- Increased security by encrypting data in flight from Gorouter to back ends
Along with these benefits, TLS routing requires additional RAM and CPU capacity on the Gorouters and the Diego cells. You can expect an increase of about 32 MB of RAM per app instance.
In this mode, the Diego Route Emitters send a modified route registration message to NATS that includes a unique identifier for the app instance, as well instructions to use TLS when communicating with the instance. See TLS to Apps and Other Back-End Services for details.
Before forwarding traffic to an app instance, Gorouter initiates a TLS handshake with an Envoy proxy that runs in each app container and listens on port 8443. In the TLS handshake, the Envoy proxy presents a certificate generated by Diego for each container which uniquely identifies the container using the same app instance identifier sent by the Router Emitter, configured in the certificate as a domain Subject Alternative Name (SAN).
If Gorouter confirms that the app instance identifier in the certificate matches the one received in the route registration message, Gorouter forwards the HTTP request over the TLS session. If the instance identifiers do not match, Gorouter transparently retries another instance of the app. If the TTL of the failed back end has expired, Gorouter prunes the route to it from its routing table.
The following table explains how Gorouter keeps routes in its routing table after TTL has expired, as long as TLS handshakes continue to succeed.
|TLS handshake succeeds AND app instance identity valid||TLS handshake fails OR app instance identity invalid|
|TTL has expired||Request forwarded||Route is pruned; transparent retry of another instance|
|TTL has not expired||Request forwarded||Route is not pruned but ineligible for requests for 30 seconds; transparent retry of another instance|
By default, Gorouter does not use TLS to verify app identity. To enable Gorouter to communicate with and validate app containers over TLS in Linux cells, perform the following steps:
In Ops Manager, click the Pivotal Application Service, Isolation Segment, or Small Footprint Runtime tile.
Navigate to the Application Containers pane.
Enable the Router uses TLS to verify application identity checkbox. With this configuration, Diego cells run an Envoy proxy for each app instance.
In this consistency mode, the Diego Route Emitters on each cell send route registration messages that include instructions for Gorouter to send unencrypted requests to the app instance. If Gorouter does not receive an update for the route within the time-to-live (TTL) interval, the route is pruned from Gorouter’s routing table. See TLS to Apps and Other Back-End Services for details.
This pruning method was developed before the alternative was available.
If Gorouter cannot establish a TCP connection with a selected application instance, Gorouter considers the instance ineligible for requests for 30 seconds and transparently attempts to connect to another application instance. Once Gorouter has established a TCP connection with an application instance, Gorouter forwards the HTTP request.
See the Round-Robin Load Balancing section below for more information about how Gorouter forwards requests to application instances.
Gorouter uses the round-robin algorithm for load balancing incoming requests to application instances. Gorouter maintains a dynamically updated list of application instances for each route, and forwards each request for a given route to the next application instance in the list.
WebSockets is a protocol providing bi-directional communication over a single, long-lived TCP connection, commonly implemented by web clients and servers. WebSockets are initiated through HTTP as an upgrade request. Gorouter supports this upgrade handshake, and holds the TCP connection open with the selected application instance.
Gorouter supports session affinity, or sticky sessions, for incoming HTTP requests to compatible apps.
With sticky sessions, when multiple instances of an app are running on CF, requests from a particular client always reach the same app instance. This allows apps to store session data specific to a user session.
To support sticky sessions, configure your app to return a
JSESSIONIDcookie in responses. The app generates a
JSESSIONIDas a long hash in the following format:
If an app returns a
JSESSIONIDcookie to a client request, the CF routing tier generates a unique
VCAP_IDfor the app instance based on its GUID in the following format:
On subsequent requests, the client must provide both the
The CF routing tier uses the
VCAP_ID cookie to forward client requests to the same app instance every time. The
JSESSIONID cookie is forwarded to the app instance to enable session continuity. If the app instance identified by the
VCAP_ID crashes, Gorouter attempts to route the request to a different instance of the app. If Gorouter finds a healthy instance of the app, it initiates a new sticky session.
Note: CF does not persist or replicate HTTP session data across app instances. If an app instance crashes or is stopped, session data for that instance is lost. If you require session data to persist across crashed or stopped instances, or to be shared by all instances of an app, store session data in a CF marketplace service that offers data persistence.
From Front-End Clients
Gorouter supports keepalive connections from clients and does not close the TCP connection with clients immediately after returning an HTTP response. Clients are responsible for closing these connections.
To Back-End Servers
If keepalive connections are disabled, Gorouter closes the TCP connection with an app instance or system component after receiving an HTTP response.
If keepalive connections are enabled, Gorouter maintains established TCP connections to back ends. Gorouter supports up to 100 idle connections to each back end:
- If an idle connection exists for a given back end, Gorouter reuses it to route subsequent requests.
- If no idle connection exists for this back end, Gorouter creates a new connection.
When you deploy an app that requires Diego cells to restart or recreate, the app may not respond to a Gorouter request before the keepalive connection breaks. The following table describes how Gorouter behaves if it cannot establish a TCP connection to an app:
|If Gorouter …||then Gorouter …|
|cannot establish a TCP connection to the routing back end for the app||retries the request three times.|
|establishes a TCP connection to the routing back end, but the app does not respond||waits 15 minutes for a response.|
In both cases, if the app still does not respond to the request, Gorouter returns a