# Securing TCP based services
The following guide demonstrates how to use Pomerium's TCP Proxying support with various TCP services such as databases and other non-HTTP protocols. It also covers integration points with them when possible.
The source files from this guide can be found on GitHub (opens new window).
# Background
When replacing a traditional VPN, there are often non-HTTP based applications which must still be reachable. Pomerium is able to provide the same type of protection to these services by using a client side application to proxy TCP connections. Authentication and authorization configuration is shared with standard HTTP routes, and the underlying transport is still encrypted between the end-user and Pomerium.
Important notes:
- Pomerium authorizes HTTP on a request-by-request basis, but TCP is authorized on a per-connection basis.
- Pomerium is only authorizing the TCP connection. It does not interact with application level authorization systems at this time.
# How it works
- Create a standard Pomerium configuration for your identity provider (IdP)
pomerium-cli
runs on your workstation, listening on loopback for TCP connections- When an inbound connection is made,
pomerium-cli
proxies the connection throughpomerium
, authenticating the user if needed - Pomerium authorizes the connection and forwards it to the upstream service
- The connecting application functions as normal
# Pre-requisites
This recipe is designed to run on a local docker-compose instance. The included configuration can be adopted for any TCP service, however.
- docker
- docker-compose
- A copy of the example repo (opens new window) checked out
- Valid credentials for your OIDC provider
- The Pomerium Client installed
- (Optional)
mkcert
to generate locally trusted certificates
# Certificates (optional)
This demo comes with its own certificates, but pomerium-cli
and your browser will not trust them by default. You may instead provide your own or use mkcert (opens new window) to generate locally trusted certificates.
After installing mkcert
, run the following inside the example repo:
mkcert -install mkcert '*.localhost.pomerium.io'
Copied!
This will install a trusted CA and generate a new wildcard certificate:
_wildcard.localhost.pomerium.io.pem
_wildcard.localhost.pomerium.io-key.pem
To provide your own certificates through another mechanism, please overwrite these files or update docker-compose.yaml
accordingly.
# Configure
# Pomerium
Update config.yaml
with your IdP settings and desired policy if adopting for your environment
authenticate_service_url: https://authenticate.localhost.pomerium.io certificates: - cert: /pomerium/cert.pem key: /pomerium/key.pem shared_secret: CHANGEME cookie_secret: CHANGEME idp_client_id: CHANGEME idp_client_secret: CHANGEME idp_provider: google policy: - from: tcp+https://redis.localhost.pomerium.io:6379 to: tcp://redis:6379 allowed_domains: - gmail.com - from: tcp+https://ssh.localhost.pomerium.io:22 to: tcp://ssh:2222 allowed_domains: - gmail.com - from: tcp+https://pgsql.localhost.pomerium.io:5432 to: tcp://pgsql:5432 allowed_domains: - gmail.com databroker_storage_type: redis databroker_storage_connection_string: redis://redis:6379
Copied!
# Docker Compose
Create a docker-compose.yaml
file to run Pomerium and, optionally, the services being demonstrated.
Included in our compose file:
- SSH
- Postgres
- Redis
version: "3" services: pomerium: image: pomerium/pomerium:master volumes: - ./_wildcard.localhost.pomerium.io.pem:/pomerium/cert.pem:ro - ./_wildcard.localhost.pomerium.io-key.pem:/pomerium/key.pem:ro - ./config.yaml:/pomerium/config.yaml:ro ports: - 443:443 redis: image: redis:latest expose: - 6379 ssh: image: linuxserver/openssh-server:latest expose: - 2222 environment: PASSWORD_ACCESS: "true" USER_PASSWORD: supersecret USER_NAME: myuser pgsql: image: postgres restart: always environment: POSTGRES_PASSWORD: supersecret expose: - 5432
Copied!
# Connect
To connect to your service, ensure pomerium-cli
is in your $PATH
and run the tcp
command, specifying the service you wish to reach.
pomerium-cli tcp [hostname]:[port]
Copied!
pomerium-cli
will select a random port on localhost
by default, but you can specify a port manually if desired. Keep reading for some specific application examples using the sample docker-compose.yaml
.
# Redis
# Start a proxy to redis in the background % pomerium-cli tcp redis.localhost.pomerium.io:6379 --listen localhost:6379 & 3:01PM INF tcptunnel: listening on 127.0.0.1:6379 # Start the redis client % redis-cli 3:01PM INF tcptunnel: opening connection dst=redis.localhost.pomerium.io:6379 proxy=redis.localhost.pomerium.io:443 secure=true 3:01PM INF tcptunnel: opening connection dst=redis.localhost.pomerium.io:6379 proxy=redis.localhost.pomerium.io:443 secure=true 3:01PM INF tcptunnel: connection established 127.0.0.1:6379> keys * 1) "type.googleapis.com/session.Session_last_version" 2) "type.googleapis.com/user.User" 3) "type.googleapis.com/session.Session" 4) "type.googleapis.com/user.User_version_set" 5) "type.googleapis.com/user.User_last_version" 6) "server_version_last_version" 7) "type.googleapis.com/session.Session_version_set" 8) "server_version_version_set" 9) "server_version" 10) "type.googleapis.com/directory.User_last_version"```
Copied!
# Postgres
In our example docker-compose, we have configured supersecret
as the password for the postgres
user.
# Start a proxy to postgres in the background % pomerium-cli tcp pgsql.localhost.pomerium.io:5432 --listen localhost:5432 & 3:07PM INF tcptunnel: listening on 127.0.0.1:5432 # Connect and list the schemas after password authentication % psql -h localhost -W -U postgres -c '\dn' Password: 3:06PM INF tcptunnel: opening connection dst=pgsql.localhost.pomerium.io:5432 proxy=pgsql.localhost.pomerium.io:443 secure=true 3:06PM INF tcptunnel: connection established List of schemas Name | Owner --------+---------- public | postgres (1 row)
Copied!
# SSH
SSH clients can make use of external programs to establish a connection to a host. Most frequently, this is for using an SSH jump host to reach a target system. However, any transport application can be used. pomerium-cli
's tcp
command can be used in conjunction with this configuration. Read on to see how.
More Info:
- https://man.openbsd.org/ssh_config.5#ProxyCommand (opens new window)
- https://www.redhat.com/sysadmin/ssh-proxy-bastion-proxyjump (opens new window)
# Setup
To configure your SSH client to use Pomerium's TCP support for SSH routes, create an entry as follows in your ssh_config
or ~/.ssh/config
:
Host *.localhost.pomerium.io ProxyCommand pomerium-cli tcp --listen - %h:%p
Copied!
- Be sure to substitute your domain for
localhost.pomerium.io
- Be sure
pomerium-cli
is in your$PATH
# Connecting
That's it! A Pomerium proxy will be started automatically whenever you ssh to a host under localhost.pomerium.io
.
In our example docker-compose, we have an SSH server configured with supersecret
as the password for myuser
.
% ssh myuser@ssh.localhost.pomerium.io 3:19PM INF tcptunnel: opening connection dst=ssh.localhost.pomerium.io:22 proxy=ssh.localhost.pomerium.io:443 secure=true 3:19PM INF tcptunnel: connection established myuser@ssh.localhost.pomerium.io's password: Welcome to OpenSSH Server 5c9f4fa5f5f7:~$
Copied!
← Synology TiddlyWiki →