| |
|
Here’s a small bash script to identify an EC2 instance as a
bastion host,
and then use SSM Session Manager to forward multiple ports through the bastion
on to other hosts.
This is useful when you want to access hosts inside your VPC (such as RDS /
Aurora), external services that enforce an IP access list (such as MongoDB
Atlas), or a mixture of those.
I’ve used scripts like this to run integration tests that talk to combinations
of services like the above.
The separate scripts to fetch the host names are just examples; they could be
passed in as arguments or environment variables instead.
#!/usr/bin/env bash
set -euo pipefail
export PAGER=cat
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
# Fetch bastion host EC2 instance ID with aws cli.
BASTION_ID=$(
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=BastionHost" "Name=instance-state-name,Values=running" \
--query "Reservations[0].Instances[0].InstanceId" \
--output text
)
echo "BASTION_ID: ${BASTION_ID}"
# Example: Use another script to get hostname A.
HOST_A=$(
bash "${SCRIPT_DIR}/get_host_a.sh" | xargs
)
echo "HOST_A: ${HOST_A}"
REMOTE_PORT_A='123456'
echo "REMOTE_PORT_A: ${REMOTE_PORT_A}"
LOCAL_PORT_A='223465'
# Example: Use another script to get hostname B.
HOST_B=$(
bash "${SCRIPT_DIR}/get_host_b.sh" | xargs
)
echo "HOST_B: ${HOST_B}"
REMOTE_PORT_B='27017'
echo "REMOTE_PORT_B: ${REMOTE_PORT_B}"
LOCAL_PORT_B='37017'
cleanup() {
echo ""
echo "Stopping tunnels..."
kill "$(jobs -p)" 2>/dev/null || true
wait 2>/dev/null || true
echo "SSH tunnels stopped"
}
trap cleanup EXIT INT TERM
# Use SSM to forward local port A through to remote port A on host A.
echo "Port forwarding ${LOCAL_PORT_A}->${HOST_A}:${REMOTE_PORT_A} through bastion..."
aws ssm start-session --target "${BASTION_ID}" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters "{
\"host\": [\"${HOST_A}\"],
\"portNumber\": [\"${REMOTE_PORT_A}\"],
\"localPortNumber\": [\"${LOCAL_PORT_A}\"]
}" &
TUNNEL_A_PID=$!
echo "TUNNEL_A_PID: ${TUNNEL_A_PID}"
sleep 1
# Use SSM to forward local port B through to remote port B on host B.
echo "Port forwarding ${LOCAL_PORT_B}->${HOST_B}:${REMOTE_PORT_B} through bastion..."
aws ssm start-session --target "${BASTION_ID}" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters "{
\"host\": [\"${HOST_B}\"],
\"portNumber\": [\"${REMOTE_PORT_B}\"],
\"localPortNumber\": [\"${LOCAL_PORT_B}\"]
}" &
TUNNEL_B_PID=$!
echo "TUNNEL_B_PID: ${TUNNEL_B_PID}"
wait
By the way, you can hire me as a
freelance AWS engineer
for your project.
View post:
AWS EC2 bastion host SSM multi port forwarding bash script
|
|
|
|