a TPROXY to block TLS connections with blocklisted certificates.
example: use on gateway
# build it
go build
# examine command line options
./certguard
certguard: -blocklist-path is required
Usage: certguard [options]
-addr string
IPv4 listen address (default "0.0.0.0")
-blocklist-path string
required directory of blocklisted PEM certificates
-fwmark string
socket bypass mark (decimal or 0x hexadecimal, nonzero uint32) (default "0x100")
-port int
TPROXY listen port (1-65535) (default 3129)
# start it
sudo ./certguard -blocklist-path /path/to/badcerts/ -addr 127.0.0.1 -port 9800
# create PBR rules
sudo ip rule add fwmark 1 table 100
sudo ip route add local 0.0.0.0/0 dev lo table 100
# create iptables rules for the gateway
sudo iptables -t mangle -N DIVERT
sudo iptables -t mangle -N CERTGUARD
sudo iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
sudo iptables -t mangle -A PREROUTING -j CERTGUARD
sudo iptables -t mangle -A DIVERT -j MARK --set-xmark 0x1
sudo iptables -t mangle -A DIVERT -j ACCEPT
sudo iptables -t mangle -A CERTGUARD -d 127.0.0.1/32 -j RETURN
sudo iptables -t mangle -A CERTGUARD -d 224.0.0.0/4 -j RETURN
sudo iptables -t mangle -A CERTGUARD -d 255.255.255.255/32 -j RETURN
sudo iptables -t mangle -A CERTGUARD -m mark --mark 0x100 -j RETURN
sudo iptables -t mangle -A CERTGUARD -p udp -j TPROXY --on-port 9800 --on-ip 127.0.0.1 --tproxy-mark 0x1
sudo iptables -t mangle -A CERTGUARD -p tcp -j TPROXY --on-port 9800 --on-ip 127.0.0.1 --tproxy-mark 0x1set default gateway/default router on hosts in LAN to box deployed as instructed above.
This TPROXY do deep packet inspection on each TCP connection, if it found the magic number of TLS handshake record with ClientHello, it onhold the traffic from TLS clients and then:
- mimics the fingerprint of TLS client and do handshake to the target TLS server
- inspect the certificate chain from TLS server
- check if any certificate in the chain exists in the blocklist, or issued (signed) by a blocklisted certificate 3.1. if true, teardown the TLS connection send TCP RESET to both end. 3.2. otherwise unhold the packet from client bearing ClientHello, start normal packet forwarding
if no TLS ClientHello is found, it just forwards the traffic as-is.
TL;DR: the recent eMudhra intermediate certificate authority (CA) compromise
Multiple eMudhra intermediate CAs are compromised with rather weak private key and was widely included in major x509 trust stores incl. Mozilla, Java, Golang, etc. Despite being revoked/removed after swiftly upstream action the updated version may not being distributed to downstream in time, rendering a diverse range of systems vulnerable to MITM attacks waged by advisories exploiting the compromised eMudhra CA certs, says:
- Container images needs a rebuild to port updated
ca-certificatepackage which distrusts compromised eMudhra CA certs - Golang application needs a rebuild with bumped
crypto/x509to make compromised eMudhra CA certs untrusted - IoT/embedded devices may still trusts the compromised eMudhra CA certs and no foreseeable updates made available
in some cases the security hole can be mitigate by system admin, says, a container rebuild of recompile of open-source software, but anyway it takes effort, what rendered the situation even worse is those unpatchable instances like IoT devices or proprietary Golang apps whose develops are lack of infosec awareness...
therefore I implemented this snippet to deploy on my homelab gateway as an universal solution to avoid TLS connection being established with blocklisted certs, says, those compromised eMudhra ones, without audit the applications, containers, smarthome devices case-by-case.
In short: NO for modern setups.
For TLS 1.2 and predecessors it is okay to just detect the Certificate payload passively, but TLS 1.3 establish (EC)DHE context at the very beginning (read more at RFC8446) and wraps the Certificate inside which rendered passive probing unfeasible.
In short: fingerprint consistency
uTLS has a feature handshaking with a TLS server with mimicked fingerprint from an existing ClientHello, the rendered distinguishing probing handshakes against real handshakes non-that-trivial and mitigates the CertGuard from being easily bypassed by an advisory returning genuine to fool the probe and blocklisted compromised cert to the real connection for MITM attack.
- Fooling the probe with genuine certs may not being avoided absolutely, sofiscated traffic fingerprinting may still capable to distinguish them out of real application traffic
- No UDP/DTLS supports made available currently
- No STARTTLS supports for selected protocols (e.g. LDAP, FTP, NFS/RPC-over-TLS, IMAP and other email-related ones, ...) made available currently
- Just an idea, not strictly validated/stress-tested under high traffic
- No guaranty or warranty made available, it is just a snippet by homelabber and for homelabbers without any SLA.
- Developping of this project is assisted with GenAI. (ChatGPT)