Open Source: Connect to Postgres Securely with PGT-Proxy

Open Source: Connect to Postgres Securely with PGT-Proxy

Open Source: Connect to Postgres Securely with PGT-Proxy

Luis Galeas

Sep 26, 2024

8 Mins read

In an effort to enhance the security and ease of database connectivity everywhere, we are excited to release PGT-Proxy into the open source. PGT-Proxy is a PostgreSQL TLS proxy that simplifies secure connections between TLS-enabled PostgreSQL clients and TLS-enabled PostgreSQL servers. PGT-Proxy is useful for secure database connectivity within the boundaries of an internal network as well as outside of it. And it can be easily deployed with Docker or used as a binary.

We built PGT-Proxy because our customers need secure connections between Ambar and their PostgreSQL databases, and we would like to extend that security to all PostgreSQL clients (developers, data analysts, application servers, and even other vendors).


Motivations

1. Simplifying Full TLS Verification with Non-Public Certificate Authorities

In today's cloud-centric world, many managed PostgreSQL services provided by cloud vendors like AWS (Aurora/RDS) and Google Cloud SQL use non-public certificate authorities (CAs) to issue TLS certificates for their databases. This presents a challenge: PostgreSQL clients need to trust these custom CAs to perform full TLS verification when connecting to the database. Expecting every client or application to install and manage these third-party certificates is impractical and introduces significant friction. What do most people do? They downgrade the connection from verified TLS to any TLS (i.e., sslmode=require instead of sslmode=full-verify), or worse, plaintext.

For example, AWS requires clients to trust a region-specific CA, adding complexity to the client configuration. Similarly, Google Cloud SQL mandates trusting a server-specific CA certificate. Managing these certificates across multiple clients can quickly become a maintenance nightmare, especially when certificates are rotated or updated.

PGT-Proxy addresses this challenge by centrally managing the trust for the PostgreSQL server's certificate authority. It performs the necessary TLS verification with the server using the custom CA and then presents a verifiable certificate to the clients—ideally one issued by a public CA that clients already trust. This means clients can perform full TLS verification without needing to install non-public CAs, simplifying the connection process while maintaining robust security.

2. Securely Exposing Private Databases Without Network Complexity

PostgreSQL servers are often hosted within private networks to enhance security. However, there are scenarios where external services or clients need access to these databases. Exposing the entire private network via VPNs or making the database publicly accessible violates the principle of least privilege and significantly increases the attack surface—a serious security concern.

While SSH tunnels can provide secure access, they introduce operational complexity and can be cumbersome for clients, especially if they have operating system or network restrictions. Load balancers and reverse proxies (like AWS NLB, AWS ALB, or Nginx) might seem like viable solutions, but they do not natively support PostgreSQL's TLS protocol. This is because PostgreSQL requires a bidirectional exchange of specific bytes before initiating the TLS handshake—a behavior not handled by standard TCP proxies.

Unfortunately, some vendors (you know who you are!) recommend practices that involve exposing databases without proper TLS verification, which is extremely irresponsible and introduces significant vulnerabilities. This not only undermines security but also places sensitive data at risk.

PGT-Proxy solves this problem by acting as a reverse proxy that understands and supports PostgreSQL's unique TLS protocol. It securely exposes the database server to external clients without compromising the security of the private network. By handling the TLS requirements appropriately, PGT-Proxy eliminates the need for complex network configurations or insecure practices, ensuring that data remains protected during transit.

3. Enforcing TLS Communication Between Clients and Servers

In some setups, PostgreSQL servers might accept plaintext (unencrypted) connections for legacy reasons or to allow trusted access within a private network. However, when clients are connecting from outside of this secure environment, it's imperative to enforce TLS encryption to protect sensitive data from interception or tampering.

PGT-Proxy ensures that all client connections are encrypted by requiring TLS communication from clients to the proxy. Even if the PostgreSQL server is configured to accept plaintext connections, PGT-Proxy communicates with the server over TLS and mandates that clients also use TLS when connecting to the proxy. This creates a secure, end-to-end encrypted channel between the client and the server.

By enforcing TLS encryption on both ends, PGT-Proxy helps organizations adhere to security best practices and regulatory requirements. It safeguards data in transit, prevents potential man-in-the-middle attacks, and ensures that sensitive information remains confidential, even when traversing insecure networks.


What is PGT-Proxy?

PGT-Proxy is an intermediary server that securely bridges TLS-enabled PostgreSQL clients and servers. It acts as a reverse proxy with support for PostgreSQL's unique TLS protocol, which requires bidirectional transmission of special bytes before initiating the TLS handshake.

Key Features:

  • TLS Termination and Initiation: PGT-Proxy handles TLS connections on both the client and server sides, ensuring end-to-end encryption.

  • Certificate Management: Supports custom certificate authorities, enabling full TLS verification even with non-public CAs.

  • Dockerized Deployment: Available as a Docker image on Docker Hub, making it easy to integrate into your existing infrastructure.

  • Small Footprint: PGT-Proxy is built on Rust, with a very lightweight Docker image that is limited to a trimmed OS and a binary file for PGT-Proxy.


How Does PGT-Proxy Solve Problems?

Enforced End-to-End TLS Encryption

PGT-Proxy enforces TLS communication from clients to servers:

  • Full TLS Verification: Clients can verify server certificates issued by a public CA, to avoid having to install private CA in client machines. And of course, private CAs are supported too.

  • Secure Communication: Protects against man-in-the-middle attacks and eavesdropping.

  • Compliance: Meets security standards and regulations requiring encrypted data in transit.

Secure Exposure Without Network Complexity

By deploying PGT-Proxy, you can securely expose your internal PostgreSQL servers to external clients without:

  • Setting up VPC peering or VPNs.

  • Configuring SSH tunnels or jumpboxes.

  • Opening up your network to potential vulnerabilities by moving it to a public subnet, or worse, converting an existing private subnet into public.


Technical Overview

Architecture Diagram

Deployment Workflow


  1. Containerization with Docker:

    • PGT-Proxy is packaged as a Docker image, simplifying deployment across various environments.

  2. Certificate Management:

    • Configure the proxy with a server certificate trusted by clients. Both public and private CA certificates work. Additionally, specify the certificate authorities that PGT-Proxy will trust from its server.

  3. Configuration:

    • Specify configuration details via Docker CMD, ENV, or ENTRYPOINT, as you prefer.

  4. Integration:

    • Update client applications to point to PGT-Proxy instead of the database server.

Sample Dockerfile

FROM ambarltd/pgt-proxy:latest

# PGT-Proxy will need to trust a set of certificate authorities
# (to be specified at runtime through "--client-ca-roots-path")

# Use a prepackaged set of root authorities such as RDS's CAs or Firefox's default trusted CAs, living at these directories:
# /etc/pgt_proxy/client_tls/aws_rds/
# /etc/pgt_proxy/client_tls/firefox/
# Or specify trusted CAs in the directory /etc/pgt_proxy/client_tls/custom_cas/ (e.g., Google Cloud SQL uses a custom CA)
RUN COPY path/to/postgres_destination_server/certificate_authority_certificates_in_pem_format/ /etc/pgt_proxy/client_tls/custom_cas/

# PGT-Proxy will need to serve TLS traffic, which requires a certificate and its corresponding private key
# (to be specified at runtime through "--server-private-key-path", "--server-certificate-path")
# The certificate needs to be trusted by all pg clients connecting through PGT-Proxy.
# Thus it is recommended to use a genuine TLS certificate issued by a public certificate authority
# that is already trusted by default by pg clients.
RUN COPY path/to/pgt_proxy/tls_certificate.pem /etc/pgt_proxy/server_tls/certificate.pem
RUN COPY path/to/pgt_proxy/tls_private_key.pem /etc/pgt_proxy/server_tls/key.pem

# Set the arguments passed to PGT-Proxy.
CMD ["--server-private-key-path", "/etc/pgt_proxy/server_tls/key.pem", \
"--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \
"--server-port", "5432", \
"--client-connection-host-or-ip", "destination.host.example.amazonaws.com", \
"--client-connection-port", "5432", \
"--client-tls-validation-host", "destination.host.example.amazonaws.com", \
"--client-ca-roots-path", "/etc/pgt_proxy/client_tls/custom_cas/"]

Security Considerations

We built PGT-Proxy with security as a paramount concern:

  • Minimal Attack Surface: Acts as a dedicated proxy for PostgreSQL, reducing unnecessary features that could introduce vulnerabilities.

  • TLS Enforcement: Requires TLS on both client and server sides.

  • Custom CA Support: Allows for full verification chains, even with private or custom CAs.

  • Isolation: By containerizing PGT-Proxy, we ensure process isolation and ease of deployment across different environments.


Getting Started with PGT-Proxy

Deployment Steps

  1. Prepare Certificates:

    • Obtain or generate TLS certificates for PGT-Proxy.

    • Collect the CA certificates trusted by your PostgreSQL server.

  2. Configure the Docker Image:

    • Use the provided Dockerfile to set up your environment.

    • Customize the command-line arguments as needed.

  3. Deploy the Container:

    • Run the Docker container in your preferred environment (e.g., AWS EC2, Kubernetes).

  4. Update Client Connections:

    • Point your PostgreSQL clients to connect to PGT-Proxy.

    • Ensure clients are configured for TLS connections.

Example Client Connection

psql "sslmode=verify-full host=pgtproxy.example.com port=5432 user=admin password=pass dbname=postgres channel_binding=disable"


Our Experience Building PGT-Proxy

Creating PGT-Proxy was driven by real-world needs we encountered with our customers:

  • Complex Integration Challenges: We saw customers struggle with complex network setups just to securely connect to their databases.

  • Security Gaps: The lack of easy-to-use tools enforcing TLS connections led us to develop a solution that fills this gap.

  • Focus on Simplicity: We aimed to make PGT-Proxy as straightforward as possible to deploy and configure, reducing the barrier to implementing strong security practices.

Conclusion

PGT-Proxy simplifies the secure connection of PostgreSQL clients to internal databases without the overhead of complex network configurations. By enforcing TLS and supporting custom certificate authorities, it enhances security while reducing deployment complexity. We invite you to use PGT-Proxy (we're already using it).

About Ambar

Ambar provides data streaming as a service, with the easiest and most correct abstraction in the market. It covers general data streaming as well as niche use cases such as event sourcing. Would you like to find out more? Shoot us a message or try our platform.

In an effort to enhance the security and ease of database connectivity everywhere, we are excited to release PGT-Proxy into the open source. PGT-Proxy is a PostgreSQL TLS proxy that simplifies secure connections between TLS-enabled PostgreSQL clients and TLS-enabled PostgreSQL servers. PGT-Proxy is useful for secure database connectivity within the boundaries of an internal network as well as outside of it. And it can be easily deployed with Docker or used as a binary.

We built PGT-Proxy because our customers need secure connections between Ambar and their PostgreSQL databases, and we would like to extend that security to all PostgreSQL clients (developers, data analysts, application servers, and even other vendors).


Motivations

1. Simplifying Full TLS Verification with Non-Public Certificate Authorities

In today's cloud-centric world, many managed PostgreSQL services provided by cloud vendors like AWS (Aurora/RDS) and Google Cloud SQL use non-public certificate authorities (CAs) to issue TLS certificates for their databases. This presents a challenge: PostgreSQL clients need to trust these custom CAs to perform full TLS verification when connecting to the database. Expecting every client or application to install and manage these third-party certificates is impractical and introduces significant friction. What do most people do? They downgrade the connection from verified TLS to any TLS (i.e., sslmode=require instead of sslmode=full-verify), or worse, plaintext.

For example, AWS requires clients to trust a region-specific CA, adding complexity to the client configuration. Similarly, Google Cloud SQL mandates trusting a server-specific CA certificate. Managing these certificates across multiple clients can quickly become a maintenance nightmare, especially when certificates are rotated or updated.

PGT-Proxy addresses this challenge by centrally managing the trust for the PostgreSQL server's certificate authority. It performs the necessary TLS verification with the server using the custom CA and then presents a verifiable certificate to the clients—ideally one issued by a public CA that clients already trust. This means clients can perform full TLS verification without needing to install non-public CAs, simplifying the connection process while maintaining robust security.

2. Securely Exposing Private Databases Without Network Complexity

PostgreSQL servers are often hosted within private networks to enhance security. However, there are scenarios where external services or clients need access to these databases. Exposing the entire private network via VPNs or making the database publicly accessible violates the principle of least privilege and significantly increases the attack surface—a serious security concern.

While SSH tunnels can provide secure access, they introduce operational complexity and can be cumbersome for clients, especially if they have operating system or network restrictions. Load balancers and reverse proxies (like AWS NLB, AWS ALB, or Nginx) might seem like viable solutions, but they do not natively support PostgreSQL's TLS protocol. This is because PostgreSQL requires a bidirectional exchange of specific bytes before initiating the TLS handshake—a behavior not handled by standard TCP proxies.

Unfortunately, some vendors (you know who you are!) recommend practices that involve exposing databases without proper TLS verification, which is extremely irresponsible and introduces significant vulnerabilities. This not only undermines security but also places sensitive data at risk.

PGT-Proxy solves this problem by acting as a reverse proxy that understands and supports PostgreSQL's unique TLS protocol. It securely exposes the database server to external clients without compromising the security of the private network. By handling the TLS requirements appropriately, PGT-Proxy eliminates the need for complex network configurations or insecure practices, ensuring that data remains protected during transit.

3. Enforcing TLS Communication Between Clients and Servers

In some setups, PostgreSQL servers might accept plaintext (unencrypted) connections for legacy reasons or to allow trusted access within a private network. However, when clients are connecting from outside of this secure environment, it's imperative to enforce TLS encryption to protect sensitive data from interception or tampering.

PGT-Proxy ensures that all client connections are encrypted by requiring TLS communication from clients to the proxy. Even if the PostgreSQL server is configured to accept plaintext connections, PGT-Proxy communicates with the server over TLS and mandates that clients also use TLS when connecting to the proxy. This creates a secure, end-to-end encrypted channel between the client and the server.

By enforcing TLS encryption on both ends, PGT-Proxy helps organizations adhere to security best practices and regulatory requirements. It safeguards data in transit, prevents potential man-in-the-middle attacks, and ensures that sensitive information remains confidential, even when traversing insecure networks.


What is PGT-Proxy?

PGT-Proxy is an intermediary server that securely bridges TLS-enabled PostgreSQL clients and servers. It acts as a reverse proxy with support for PostgreSQL's unique TLS protocol, which requires bidirectional transmission of special bytes before initiating the TLS handshake.

Key Features:

  • TLS Termination and Initiation: PGT-Proxy handles TLS connections on both the client and server sides, ensuring end-to-end encryption.

  • Certificate Management: Supports custom certificate authorities, enabling full TLS verification even with non-public CAs.

  • Dockerized Deployment: Available as a Docker image on Docker Hub, making it easy to integrate into your existing infrastructure.

  • Small Footprint: PGT-Proxy is built on Rust, with a very lightweight Docker image that is limited to a trimmed OS and a binary file for PGT-Proxy.


How Does PGT-Proxy Solve Problems?

Enforced End-to-End TLS Encryption

PGT-Proxy enforces TLS communication from clients to servers:

  • Full TLS Verification: Clients can verify server certificates issued by a public CA, to avoid having to install private CA in client machines. And of course, private CAs are supported too.

  • Secure Communication: Protects against man-in-the-middle attacks and eavesdropping.

  • Compliance: Meets security standards and regulations requiring encrypted data in transit.

Secure Exposure Without Network Complexity

By deploying PGT-Proxy, you can securely expose your internal PostgreSQL servers to external clients without:

  • Setting up VPC peering or VPNs.

  • Configuring SSH tunnels or jumpboxes.

  • Opening up your network to potential vulnerabilities by moving it to a public subnet, or worse, converting an existing private subnet into public.


Technical Overview

Architecture Diagram

Deployment Workflow


  1. Containerization with Docker:

    • PGT-Proxy is packaged as a Docker image, simplifying deployment across various environments.

  2. Certificate Management:

    • Configure the proxy with a server certificate trusted by clients. Both public and private CA certificates work. Additionally, specify the certificate authorities that PGT-Proxy will trust from its server.

  3. Configuration:

    • Specify configuration details via Docker CMD, ENV, or ENTRYPOINT, as you prefer.

  4. Integration:

    • Update client applications to point to PGT-Proxy instead of the database server.

Sample Dockerfile

FROM ambarltd/pgt-proxy:latest

# PGT-Proxy will need to trust a set of certificate authorities
# (to be specified at runtime through "--client-ca-roots-path")

# Use a prepackaged set of root authorities such as RDS's CAs or Firefox's default trusted CAs, living at these directories:
# /etc/pgt_proxy/client_tls/aws_rds/
# /etc/pgt_proxy/client_tls/firefox/
# Or specify trusted CAs in the directory /etc/pgt_proxy/client_tls/custom_cas/ (e.g., Google Cloud SQL uses a custom CA)
RUN COPY path/to/postgres_destination_server/certificate_authority_certificates_in_pem_format/ /etc/pgt_proxy/client_tls/custom_cas/

# PGT-Proxy will need to serve TLS traffic, which requires a certificate and its corresponding private key
# (to be specified at runtime through "--server-private-key-path", "--server-certificate-path")
# The certificate needs to be trusted by all pg clients connecting through PGT-Proxy.
# Thus it is recommended to use a genuine TLS certificate issued by a public certificate authority
# that is already trusted by default by pg clients.
RUN COPY path/to/pgt_proxy/tls_certificate.pem /etc/pgt_proxy/server_tls/certificate.pem
RUN COPY path/to/pgt_proxy/tls_private_key.pem /etc/pgt_proxy/server_tls/key.pem

# Set the arguments passed to PGT-Proxy.
CMD ["--server-private-key-path", "/etc/pgt_proxy/server_tls/key.pem", \
"--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \
"--server-port", "5432", \
"--client-connection-host-or-ip", "destination.host.example.amazonaws.com", \
"--client-connection-port", "5432", \
"--client-tls-validation-host", "destination.host.example.amazonaws.com", \
"--client-ca-roots-path", "/etc/pgt_proxy/client_tls/custom_cas/"]

Security Considerations

We built PGT-Proxy with security as a paramount concern:

  • Minimal Attack Surface: Acts as a dedicated proxy for PostgreSQL, reducing unnecessary features that could introduce vulnerabilities.

  • TLS Enforcement: Requires TLS on both client and server sides.

  • Custom CA Support: Allows for full verification chains, even with private or custom CAs.

  • Isolation: By containerizing PGT-Proxy, we ensure process isolation and ease of deployment across different environments.


Getting Started with PGT-Proxy

Deployment Steps

  1. Prepare Certificates:

    • Obtain or generate TLS certificates for PGT-Proxy.

    • Collect the CA certificates trusted by your PostgreSQL server.

  2. Configure the Docker Image:

    • Use the provided Dockerfile to set up your environment.

    • Customize the command-line arguments as needed.

  3. Deploy the Container:

    • Run the Docker container in your preferred environment (e.g., AWS EC2, Kubernetes).

  4. Update Client Connections:

    • Point your PostgreSQL clients to connect to PGT-Proxy.

    • Ensure clients are configured for TLS connections.

Example Client Connection

psql "sslmode=verify-full host=pgtproxy.example.com port=5432 user=admin password=pass dbname=postgres channel_binding=disable"


Our Experience Building PGT-Proxy

Creating PGT-Proxy was driven by real-world needs we encountered with our customers:

  • Complex Integration Challenges: We saw customers struggle with complex network setups just to securely connect to their databases.

  • Security Gaps: The lack of easy-to-use tools enforcing TLS connections led us to develop a solution that fills this gap.

  • Focus on Simplicity: We aimed to make PGT-Proxy as straightforward as possible to deploy and configure, reducing the barrier to implementing strong security practices.

Conclusion

PGT-Proxy simplifies the secure connection of PostgreSQL clients to internal databases without the overhead of complex network configurations. By enforcing TLS and supporting custom certificate authorities, it enhances security while reducing deployment complexity. We invite you to use PGT-Proxy (we're already using it).

About Ambar

Ambar provides data streaming as a service, with the easiest and most correct abstraction in the market. It covers general data streaming as well as niche use cases such as event sourcing. Would you like to find out more? Shoot us a message or try our platform.

Over $3B in Transactions Processed

Over $3B in Transactions Processed

Discover what Ambar could do for you!

Discover what Ambar could do for you!