I am using AWS CLI in a Docker container to open a port forwarding session to a remote host via AWS SSM on an EC2 instance. So that I can access the port from outside of the Docker container, I am mapping it in Docker so that it is available on my own host.
The issue now is that any connection to this port from outside of the Docker container is immediately closed. My guess is that this is due to safeguards in the port forwarding session, which will allow connections to the forwarded port only from localhost
. However, when I am accessing the port from my host machine, it will not show up as localhost
and the connection is immediately terminated.
How can I configure the port forwarding session so that I can also create connections to this port that do not originate from localhost
?
I have already had a look at the SSM document AWS-StartPortForwardingSessionToRemoteHost
to see if I can modify this. However, I could not find documentation that would give me the possible values for properties.type
, which I assume is the culprit for only accepting connections from localhost
.
Full content of the AWS-StartPortForwardingSessionToRemoteHost
SSM document:
{
"schemaVersion": "1.0",
"description": "Document to start port forwarding session over Session Manager to remote host",
"sessionType": "Port",
"parameters": {
"portNumber": {
"type": "String",
"description": "(Optional) Port number of the server on the instance",
"allowedPattern": "^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
"default": "80"
},
"localPortNumber": {
"type": "String",
"description": "(Optional) Port number on local machine to forward traffic to. An open port is chosen at run-time if not provided",
"allowedPattern": "^([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
"default": "0"
},
"host": {
"type": "String",
"description": "(Optional) Hostname or IP address of the destination server",
"allowedPattern": "^[^,$^&\\(\\)!;'\"<>\\`{}\\[\\]\\|#=]{3,}$",
"default": "localhost"
}
},
"properties": {
"portNumber": "{{ portNumber }}",
"type": "LocalPortForwarding",
"localPortNumber": "{{ localPortNumber }}",
"host": "{{ host }}"
}
}
Dockerfile
:
FROM amazon/aws-cli
RUN curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm" -o "session-manager-plugin.rpm" && yum install -y ./session-manager-plugin.rpm && yum install -y telnet
Docker command:
docker run \
--rm \
-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \
-p 5432:5432 \
-ti \
awscli-ssm \
ssm start-session \
--target <my-ec2-instance-id> \
--region <my-region> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["<my-rds-host>.rds.amazonaws.com"],"portNumber":["5432"], "localPortNumber":["5432"]}'
When running telnet localhost 5432
in the Docker container, connection remains open:
bash-4.2# telnet localhost 5432
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
When running telnet localhost 5432
from outside of the Docker container, connection is closed immediately:
chris@chris-machine:~$ telnet localhost 5432
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
Not a fix, but at least a workaround: Create a local tunnel inside the Docker container, thereby making it look to AWS like the connection is coming from localhost
.
Dockerfile
:
FROM amazon/aws-cli
RUN curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm" -o "session-manager-plugin.rpm" && yum install -y ./session-manager-plugin.rpm
RUN yum install -y socat
Build it: docker build . -t awscli-ssm
Run it (note the different port supplied to -p
):
docker run \
--rm \
-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \
-p 13000:13000 \
-ti \
--entrypoint "" \
awscli-ssm \
bash -c "socat tcp-listen:13000,reuseaddr,fork tcp:localhost:5432 & \
aws ssm start-session \
--target <my-ec2-instance-id> \
--region <my-region> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{\"host\":[\"<my-rds-host>.rds.amazonaws.com\"],\"portNumber\":[\"5432\"], \"localPortNumber\":[\"5432\"]}'
Your connection is now available outside of the container on localhost:13000
.