Proxy on GCP – Harder, Better, Faster, Stronger 🤖

The week before the pentest…

Work it harder, make it better
Do it faster, makes us stronger
More than ever, hour after
Hour, work is never over


French army band medleys Daft Punk following Bastille Day parade

The situation is nothing to write home about. C2 malware, ransomware, default telemetry, use of plaintext protocols across the Internet, escalating data egress charges – you name it – this one unplugged gap in the Cloud, the outbound connections originating from your deployments, keeps on giving (or taking.)

With no human-readable visibility on any egress flows, not much you can do with all those IP addresses in the flow logs. Talk about flying blind. It’s time to install a filtering proxy, and Squid is the word on the grapevine.

Let’s take a deep-dive 🔎

A minimal allowlisting Squid config

# /etc/squid/squid.conf

cache deny all

# ensure only trusted client subnets are listed
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16

acl allowlist dstdomain "allowlist.txt"

http_access allow localnet allowlist
http_access deny all

http_port 3128
# /etc/squid/allowlist.txt

foo.auth0.com
mtls.okta.com

# from Thu, 29 Aug 2021 06:00:00 +0000 cutover to the new subdomain at auth0.com
bar.auth0.com

Now the only things we need to worry about are:

➟ tying specific allowlists or policies to specific applications by introducing authentication or creating ACLs per subnet (and run an application per subnet)
➟ develop a mechanism to change config files on the fly, perhaps by pulling down from a bucket every so often and sending the squid process a HUP signal or redeploying stateless containers and monitoring the fronting load balancer
➟ create a log trail for auditability of changes made to these config files and subsequent production deployments
➟ ensure logs are parsed and can be searched effectively at the indexer
➟ perhaps suppress the healthcheck logs
➟ set minimum inbound and outbound TLS version levels
➟ create TCP port-based ACLs for letting SSH through, allowed to specific static IP addresses
reconfigure all applications with http_proxy, https_proxy and no_proxy config, so they route http requests efficiently


…and the proxy server config grows tentacles 🦑

# /etc/squid/squid.conf
...

# here be dragons 🀄
🐉
🐲

…scripts to “orchestrate” ♫ emerge

#!/bin/bash
# don't forget to install bash

set -e # at least stop if a command fails, without a helpful error message

...

Write it, cut it, paste it, save it
Load it, check it, quick - rewrite it


…applications become less portable, less testable

val proxyHost = "squid-somewhere.some-zone.local"
val proxyPort = 3128

val httpsProxyTransport = ClientTransport.httpsProxy(InetSocketAddress.createUnresolved(proxyHost, proxyPort))

val settings = ConnectionPoolSettings(system).withTransport(httpsProxyTransport)
Http().singleRequest(HttpRequest(uri = "https://foo.auth0.com"), settings = settings)

Maybe a proxy-less solution?

A discriminating, next-gen firewall might just be what you need instead 💊

So, how does discrimiNAT compare to Squid then?

 SquiddiscrimiNAT
Sufficient Depth of Checks🟢 yes
proxies terminate incoming connections, read metadata, and launch new outbound connections, therefore, working around the need to carry out more checks because they are acting on the client’s behalf
🟢 yes
inspects raw packets for protocol-level anomalies and also conducts asynchronous, out-of-band DNS checks to verify hostnames against IP addresses
Protocol Downgrade Protection🟠 maybe
such a capability must be explicitly configured in the config file for both requests and responses of a TLS handshake
🟢 yes
enforces minimum protocol level versions (such as 1.2 for TLS), as per contemporary standards, for both sides of a handshake
Per-Application Policies🟠 maybe
will require apps to proxy-authenticate so they can be identified and corresponding ACLs applied, or hardcoding of distinct source IP ranges/subnets mapped to specific policies in the config file
🟢 yes
integrates with the Cloud providers' native application-level firewall constructs such as Security Groups in AWS and Firewall Rules in GCP, deriving policies from these resources' built-in fields
Monitor Flows🟠 maybe
per-application policies are difficult to accomplish as discussed, therefore, any relaxation of enforcement (so logs can be collected) puts the entire VPC at risk. Morever, the entire range of ports and protocols accessed by an application will surely be missed by Squid’s typical network topology
🟢 yes
the see-thru mode is able to capture and generate filterable logs for specific applications, therefore, keeping policies enforced for the rest of the VPC. Logs also indicate whether current rules would cover the traffic seen or not and can be filtered on this criteria too
SSH (or SFTP) Protocol Support🔴 no
proxying at a TCP port level does not validate protocol soundness, requires workarounds on the client-side, and only IP address-based policies may be applied; it is an HTTP proxy after all
🟢 yes
protocol is implemented natively for deep packet inspection, and policies can be applied on destination FQDNs
TLS (or HTTPS) Protocol Support🟢 yes
proxies have their own implementation written in low-level languages such as C and C++, linked to common libraries such as OpenSSL
🟢 yes
deep packet inspection engines do not implement the protocols per se but only a subset of the specifications so packets on the wire can be parsed; discrimiNAT is written in Rust, a low-level but memory-safe language
TLS Decryption🟠 maybe
if the proxy’s CA certificates are installed on clients to trust, it can be configured to decrypt TLS connections and inspect their payload; the onward connection to the intended destination would be initiated by the proxy, and only the proxy will see the true SSL certificate; the client will see an SSL certificate from the proxy, and the boundary of unencrypted data will move to the proxy node
🔴 no
at this time, discrimiNAT does not implement decryption of the full payload or installation of CA keys; the boundary of unencrypted data does not move to this gateway at the internet/public edge of your network
Connection Termination🔴 yes
proxies by definition terminate the inbound connection and launch a similar one outbound; this adds huge latency with TCP and TLS handshakes having to be carried out twice for each connection, and cipher preferences from the client can get diluted
🟢 no
packets are inspected as they flow on the wire with deep packet inspection; since no connections are terminated or new ones initiated, all original handshake preferences are preserved; no impact on latency either
Cloud-Native Rules Management🔴 no
rules in the form of ACLs are described in config files, and any updates to them would involve delivering changes to such files and sending a HUP signal to Squid’s processes or restarting them; this could involve a lot of work, especially with auditability thrown in
🟢 yes
config is pulled from Cloud providers' native firewall constructs such as Security Groups in AWS and Firewall Rules in GCP, therefore enabling the use of their web consoles, any existing infrastructure as code tools such as Terraform, and with auditability since it’s an integral part of the Cloud platform
Cloud-Native Logging🔴 no
an HTTP proxy’s logs are very application-layer oriented and are usually very noisy; shipping these into the Cloud platform’s logging service in a parseable format requires fragmented, delicate config
🟢 yes
whether it’s CloudWatch or StackDriver, proper, structured flow and audit logs are separately indexed in mere seconds with rich security-oriented metadata
Application Config Required🔴 yes
a smooth operation can only be achieved if the applications have HTTP_PROXY, HTTPS_PROXY and NO_PROXY configured appropriately; this is so that http:// and https:// traffic is force-routed through the proxy at the application-layer and the inter-VPC, intra-VPC and instance metadata traffic on the link-local interface does not route through the proxy
🟢 no
zero config change required on the applications no matter which application-layer protocol is involved; all routing is carried out as natively defined on the Cloud platform’s route tables and firewall rules
Transparent Operation🟠 maybe
with complex routing and a range of ports defined upfront, and with limitations around TLS interception, some transparent operation can be achieved
🟢 yes
since this replaces the NAT, packets are naturally routed via it at an IP level, and the use of deep packet inspection enables it to work by observation rather than termination
Safe To Operate🔴 no
with hundreds of config options and opportunities for policy-bypass with the use of port-based ACLs tied together with IP addresses in hand-crafted config files, it is easy to end up with a security stance that isn’t safe, even by knowledgeable experts, and may inadvertently have holes in it
🟢 yes
has been designed upfront to not have features that can downgrade the security stance expected of an internet gateway, and is built for and tested thoroughly on the supported Cloud platforms – so no specialised knowledge is required to configure and operate it, and the security champions can confidently hand it over for self-service operation
Lecture 18 and Lecture 19 from “Computer and Network Security” at Purdue University are an excellent read for those interested in an in-depth course on proxies vs packet-filtering firewalls.

⛅ Enter DX: Developer Experience

The discrimiNAT firewall has been engineered from the ground up with DX in mind.

🖝 No application config required for when and when not to use a proxy 🖣

$ env | grep _PROXY
$

🖝 Firewall config in Cloud console, precisely where it should be 🖣

🖝 Keep using Terraform or any other Infrastructure as Code tool 🖣

fqdns_saas_auth = [
    "foo.auth0.com",
    "mtls.okta.com"
  ]

🖝 Support the SSH protocol as well for those SFTP and git clone jobs 🖣

git clone [email protected]:EnterpriseQualityCoding/FizzBuzzEnterpriseEdition.git

🖝 Structured logs with well thought out fields in your Cloud’s logging service 🖣

{
  "outcome": "allowed",
  "fqdn": "foo.auth0.com",
  ...
}

🖝 Meet regulatory and compliance standards of encryption out of the box 🖣

{
  "proto": "tls",
  "proto_v": "1.2",
  ...
}
🖝 Pass that pentest 🖣

We are human... after all
Much in common. After all


Next steps

🚀 Launch a free trial now from the GCP Marketplace

🚀 Get in touch with our stellar DevSecOps who will:

  • not only guide you through the best architecture for your use-case
  • but also troubleshoot any issues you may encounter
  • and answer any geeky questions on protocols and whatnot

🚀 See our Quick Start guide for GCP

🚀 Watch a brief demo video