Q: A development team exposed Docker's TCP socket on port 2375 (`-H tcp://0.0.0.0:2375`) to allow remote builds from a Jenkins server. Within 4 hours, internet botnets scanned the port, invoked the Docker API to launch privileged containers mounting the host root filesystem, and deployed Monero cryptominers across the server fleet. You must disinfect the servers, shut down unencrypted port 2375, and implement hardened mutual TLS (mTLS) authentication on port 2376 using client certificates.
Secure remote Docker engine TCP sockets. Prevent unauthenticated remote code execution and cryptojacking worm attacks by configuring strict mutual TLS (mTLS) authentication on port 2376.
Want to master this scenario in a live sandbox? KodeKloud's Docker Certified Associate (DCA) Hands-On Lab Course covers this exact problem with hands-on terminal drills.
🛠️ Production Runbook & Step-by-Step Resolution
Understand the Severity of Unauthenticated Docker API Exposure
Exposing Docker's API without TLS on port 2375 allows anyone who can reach the port to execute arbitrary commands as host root. An attacker simply issues a POST request to `/containers/create` with a privileged Alpine container mounting `/` from the host.
# Demonstration of the attack vector:
curl -X POST http://victim-node:2375/containers/create \
-H "Content-Type: application/json" \
-d '{"Image":"alpine","Cmd":["sh","-c","echo pwned > /host/etc/motd"],"HostConfig":{"Binds":["/:/host"]}}'
Generate CA, Server, and Client Certificates for mTLS
Create a dedicated Certificate Authority (CA), a server certificate with the host IP/FQDN in the Subject Alternative Name (SAN), and a client certificate for authentication.
# 1. Create CA
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -subj "/CN=Docker-CA"
# 2. Create Server Key and Cert with SAN
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=docker-host.internal" -sha256 -new -key server-key.pem -out server.csr
echo "subjectAltName = DNS:docker-host.internal,IP:10.0.1.50" > extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
# 3. Create Client Key and Cert
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
echo "extendedKeyUsage = clientAuth" > extfile-client.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out cert.pem -extfile extfile-client.cnf
Configure Docker Daemon for Mandatory TLS Verification
Configure `/etc/docker/daemon.json` to bind to port 2376 with `tlsverify: true`, referencing the generated CA and server certificate.
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"tls": true,
"tlsverify": true,
"tlscacert": "/etc/docker/certs/ca.pem",
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}
EOF
sudo systemctl restart docker
Connect Securely from Remote Client Using TLS Flags
Test the connection from the remote Jenkins runner. Verify that connecting without client certificates fails, and connecting with certificates succeeds.
# Unauthenticated connection fails:
curl https://10.0.1.50:2376/version --insecure
# Output: Bad Request / Client sent an HTTP request to an HTTPS server
# Authenticated connection via Docker CLI succeeds:
docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=tcp://10.0.1.50:2376 version
- W
- e
- e
- r
- a
- d
- i
- c
- a
- t
- e
- d
- r
- e
- m
- o
- t
- e
- c
- o
- n
- t
- a
- i
- n
- e
- r
- t
- a
- k
- e
- o
- v
- e
- r
- a
- n
- d
- c
- r
- y
- p
- t
- o
- j
- a
- c
- k
- i
- n
- g
- v
- u
- l
- n
- e
- r
- a
- b
- i
- l
- i
- t
- i
- e
- s
- b
- y
- s
- h
- u
- t
- t
- i
- n
- g
- d
- o
- w
- n
- u
- n
- e
- n
- c
- r
- y
- p
- t
- e
- d
- D
- o
- c
- k
- e
- r
- p
- o
- r
- t
- 2
- 3
- 7
- 5
- a
- c
- r
- o
- s
- s
- a
- l
- l
- b
- u
- i
- l
- d
- h
- o
- s
- t
- s
- .
- W
- e
- c
- o
- n
- f
- i
- g
- u
- r
- e
- d
- m
- u
- t
- u
- a
- l
- T
- L
- S
- o
- n
- p
- o
- r
- t
- 2
- 3
- 7
- 6
- r
- e
- q
- u
- i
- r
- i
- n
- g
- v
- a
- l
- i
- d
- x
- 5
- 0
- 9
- c
- l
- i
- e
- n
- t
- c
- e
- r
- t
- i
- f
- i
- c
- a
- t
- e
- s
- ,
- e
- n
- s
- u
- r
- i
- n
- g
- t
- h
- a
- t
- o
- n
- l
- y
- a
- u
- t
- h
- e
- n
- t
- i
- c
- a
- t
- e
- d
- C
- I
- r
- u
- n
- n
- e
- r
- s
- p
- r
- e
- s
- e
- n
- t
- i
- n
- g
- v
- a
- l
- i
- d
- c
- r
- y
- p
- t
- o
- g
- r
- a
- p
- h
- i
- c
- c
- r
- e
- d
- e
- n
- t
- i
- a
- l
- s
- c
- a
- n
- i
- n
- t
- e
- r
- a
- c
- t
- w
- i
- t
- h
- t
- h
- e
- D
- o
- c
- k
- e
- r
- d
- a
- e
- m
- o
- n
- .