# 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-cliruns on your workstation, listening on loopback for TCP connections- When an inbound connection is made,
pomerium-cliproxies 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)
mkcertto 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'
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
# 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
# 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]
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"```
# 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)
# 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
- Be sure to substitute your domain for
localhost.pomerium.io - Be sure
pomerium-cliis 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:~$
← Synology TiddlyWiki →