TCP over HTTP Support
In addition to managing HTTP based applications, Pomerium can be used to protect non-HTTP systems with the same consistent authorization policy. This is achieved by tunneling TCP over HTTP with the help of a client side command built into pomerium-cli
.
Operations and engineering teams frequently require access to lower level administrative and data protocols such as SSH, RDP, Postgres, MySQL, Redis, etc.
Internally, Pomerium uses the CONNECT
method to establish the TCP tunnel.
To minimize issues with TCP support, Pomerium should not be placed behind another HTTP proxy. Instead, configure your load balancer in L4 or TCP mode.
Otherwise, the HTTP proxy in front of Pomerium must know how to properly handle the CONNECT
command and proxy it upstream. This capability will be specific to each proxy implementation.
Configure TCP routes
TCP configuration is simple. Just specify the correct scheme and ports in your route to
and from
fields.
Example:
routes:
- from: tcp+https://redis.corp.example.com:6379
to: tcp://redis.internal.example.com:6379
policy:
- allow:
or:
- email:
is: contractor@not-example.com
- claim/groups: 'datascience@example.com'
When creating TCP routes, note the following:
- When configuring a TCP route, any HTTP specific settings such as
regex_rewrite_pattern
orset_request_headers
have no effect. - While data is encrypted from a user system to Pomerium's proxy, the underlying application protocol must also support encryption for data to be fully encrypted end-to-end. Otherwise, traffic from the Pomerium Proxy service to the upstream service will be unencrypted.
- The ports in
from
andto
are independent. Users only need to know thefrom
URL to connect. Theto
can be changed without end user participation. - The port defined in
from
does not dictate what port the tunneled traffic uses. This will always be the port defined byaddress
in your Pomerium configuration (443
by default). The port instead differentiates multiple routes to the same hostname for different services.
Connect to TCP Routes
While HTTP routes can be consumed with just a normal browser, pomerium-cli
or Pomerium Desktop must serve as a proxy for TCP routes. See Pomerium Desktop and CLI Clients for more information.
To connect, you normally need just the external hostname and port of your TCP route:
$ pomerium-cli tcp redis.localhost.pomerium.io:6739
2023/10/02 11:19:59 listening on 127.0.0.1:52046
By default, pomerium-cli
will start a listener on loopback on a random port.
On first connection, you will be sent through a standard Pomerium HTTP authentication flow. After completing this, your TCP connection should be established!
$ redis-cli -h localhost -p 52046
localhost:52046> keys *
(empty array)
localhost:52046>
Advanced capabilities
Listen configuration
You may specify an optional address and port for the tcp
command to listen on.
-
specifies that STDIN and STDOUT should be directly attached to the remote TCP connection. This is useful for SSH or for sending data through a shell pipe.
Bastion host
If the Pomerium proxy is not reachable through port 443
or the route is not in external DNS, you can use Pomerium as a bastion host using the extended TCP URL syntax in your route definition:
from: tcp+https://proxy.corp.example.com:8443/redis.internal.example.com:6379
And then using the same URL in the pomerium-cli command invocation:
pomerium-cli tcp tcp+https://proxy.corp.example.com:8443/redis.internal.example.com:6379
The command above connects to https://pomerium.corp.example.com:8443
and then requests the TCP route for redis.internal.example.com:6379
.
Client certificates
If Pomerium is configured to require client certificates, you will also need to provide a client certificate and private key when invoking the pomerium-cli
command.
You can specify these either by using PEM files, or (new in v0.23.0) by searching for a certificate in the system trust store (on macOS and Windows only).
To specify a client certificate and key using PEM files:
pomerium-cli tcp --client-cert cert.pem --client-key key.pem redis.corp.example.com:6379
To search for a client certificate in the system trust store:
pomerium-cli tcp --client-cert-from-store redis.corp.example.com:6379
This will search the Keychain (on macOS) or the Windows certificate store (on Windows) for a client certificate and private key, based on the trusted CA names advertised by Pomerium in the TLS handshake.
If you need to select between multiple matching client certificates, you can additionally filter based on the Distinguished Name of the certificate's Issuer and/or the certificate Subject.
For example, to filter for a certificate directly issued by a CA with the Common Name "My Trusted CA":
pomerium-cli tcp --client-cert-from-store --client-cert-issuer "CN=My Trusted CA" redis.corp.example.com:6379
Or, to filter for a certificate whose Subject contains the Organizational Unit Name "My Department":
pomerium-cli tcp --client-cert-from-store --client-cert-subject "OU=My Department" redis.corp.example.com:6379
See the reference page for more details about the certificate name filter syntax.
Proxy chaining support
The TCP route example above uses a to
URL with the scheme tcp://
. For a TCP route like this, Pomerium will open a raw TCP connection to the upstream service.
Alternatively, you can configure a TCP route to proxy an HTTP CONNECT request to the upstream service. This is useful if you want to place another HTTP-to-TCP proxy behind Pomerium.
To configure Pomerium to chain TCP connection requests:
routes:
- from: tcp+https://example.corp.com:10002
to: http://second-proxy.example.corp.com:10003
The guides below demonstrate how to proxy TCP tunnels with Pomerium to well-known services: