3.4
Bastion Hosts, NAT Instances and NAT Gateways
Reaching private servers safely, and giving them outbound internet without exposing them: NAT step by step, high availability and cost.
30 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Give administrators a shell on private servers with a bastion host, and configure its security groups correctly.
- Explain why Session Manager (and EC2 Instance Connect Endpoint) is the modern answer when the exam says “no inbound ports”.
- Describe how NAT lets private servers reach the internet while staying unreachable from it.
- Build a NAT instance correctly (source/destination check, Elastic IP, routes) and know why it is legacy.
- Configure NAT gateways for high availability, compare zonal and Regional NAT gateways, and know when a private NAT gateway is the answer.
#Two problems that private subnets create
Lesson 3.3 made the database and application servers private: no public address, no route to the internet gateway. That is the right default, but it creates two everyday problems:
- Getting in to administer them. How does an engineer open a shell on a server that cannot be reached from the internet?
- Letting them out. How does a private server download security patches, pull a container image or call a payment API, without becoming reachable from the internet?
The first is solved by a bastion host (or, better, by Session Manager). The second by NAT: a NAT gateway or, in older designs, a NAT instance.
#Bastion hosts
A bastion host (also called a jump box) is a small EC2 instance in a public subnet with a public or Elastic IP. Administrators SSH (port 22, Linux) or RDP (port 3389, Windows) to the bastion first, and from there to the private servers.
The whole design lives or dies on two security groups:
| Security group | Inbound rule | Why |
|---|---|---|
| Bastion host | Port 22 (or 3389) only from the admins’ address, for example 203.0.113.25/32 or the office range | Never 0.0.0.0/0: an SSH port open to the world is attacked within minutes |
| Private servers | Port 22 (or 3389) only from the bastion’s security group (sg-…) | Referencing the group, not an IP, keeps working when the bastion is replaced, and excludes every other machine in the public subnet |
Getting a shell on a private server
The database server has no public address. Compare the classic bastion host with Session Manager, which needs no open port at all.
Scenario
Bastion SG: SSH from 203.0.113.25/32. Database SG: SSH from the bastion’s security group.
The admin connects with SSH (port 22) to the bastion’s public address. The bastion’s security group allows port 22 only from the admin’s own address, 203.0.113.25/32.
#The modern answer: no inbound port at all
A bastion is still a server: you must patch it, protect its SSH keys, keep its allowed IP list current, and pay for it. AWS offers two ways to avoid it entirely:
- AWS Systems Manager Session Manager. An agent on the instance (pre-installed on Amazon Linux and recent Windows AMIs) makes an outbound HTTPS connection to the Systems Manager service. You open a shell from the console or CLI, and IAM decides who may connect to which instance. No inbound rules, no port 22, no SSH keys, no public IP, and every session can be logged to S3 or CloudWatch Logs. The instance needs an IAM role with Systems Manager permissions and a path out (a NAT gateway or VPC endpoints for Systems Manager).
- EC2 Instance Connect Endpoint. An endpoint you create in the VPC that tunnels SSH or RDP from the console or CLI to private instances, authenticated by IAM, without a bastion or public IP.
#NAT: out yes, in no
NAT (Network Address Translation) rewrites the source address of outgoing packets. A NAT device in a public subnet takes a packet from a private server (10.0.10.10), replaces the source with its own public address, remembers the pairing in a translation table, and when the reply comes back, reverses the swap.
The crucial property is in the table: an entry exists only because a server inside started the conversation. A packet that arrives from the internet without a matching entry has nowhere to go and is dropped. That gives private servers outbound access with no inbound exposure.
A NAT gateway lets private servers out, never in
An app server in a private subnet downloads security patches. Follow the addresses as they are rewritten.
Scenario
Private route table: 0.0.0.0/0 → nat-… · Public route table: 0.0.0.0/0 → igw-…
Leaving the app server
Source
10.0.10.10:43122
Destination
198.51.100.30:443
The app server connects to the patch server. Its subnet’s route table sends 0.0.0.0/0 to the NAT gateway, which sits in a public subnet.
#NAT instances (the old way)
Before NAT gateways existed, you ran NAT yourself on an EC2 instance. It still appears in exam questions as the “older option”, mostly around one setting.
How to build one:
- Launch it in a public subnet with an Elastic IP (or public IP).
- Disable the source/destination check on the instance. By default every EC2 instance drops traffic that is not addressed from or to itself; a NAT instance forwards other machines’ traffic, so with the check on it silently discards everything. This is the exam’s favourite NAT question.
- In the private subnets’ route table, send
0.0.0.0/0to the NAT instance (i-…). - Its security group must allow HTTP/HTTPS from the private subnets inbound, and HTTP/HTTPS to the internet outbound (plus SSH from your network if you administer it).
Why nobody builds them for new systems:
- You manage everything: OS patches, the NAT software, monitoring.
- No built-in high availability: if the instance or its AZ fails, private servers lose the internet until a script or Auto Scaling group replaces it.
- Bandwidth is limited by the instance type.
- The ready-made NAT AMI that AWS used to provide was based on Amazon Linux 1, which reached end of support; today you would have to configure NAT on a current image yourself.
#NAT gateways
A NAT gateway is NAT as a managed service, and the default choice today.
| Property | Detail |
|---|---|
| Fully managed | No OS, no patching, no software to run. |
| Bandwidth | Starts at 5 Gbps and scales automatically up to 100 Gbps. |
| Placement | A (zonal, public) NAT gateway is created in a specific AZ, in a public subnet, and uses an Elastic IP. It is redundant within its AZ. |
| Needs an internet gateway | Its subnet must route 0.0.0.0/0 to the VPC’s IGW; without one, it cannot reach the internet. |
| No security groups | You cannot attach a security group to a NAT gateway; control traffic with security groups on the instances and network ACLs on the subnets. |
| Who can use it | Instances in other subnets route to it; it is not used by instances in its own (public) subnet, which go to the IGW directly. |
| IPv4 only for internet egress | For IPv6 servers that need outbound-only internet, use an egress-only internet gateway instead (Chapter 22). |
| Cost | Charged per hour and per GB processed, on top of normal data transfer. |
#NAT instance vs NAT gateway
| NAT instance | NAT gateway | |
|---|---|---|
| Management | You (OS, software, patches) | AWS |
| Availability | Build it yourself (scripts, Auto Scaling) | Redundant within its AZ; one per AZ for full HA |
| Bandwidth | Depends on instance type | 5 Gbps, scaling to 100 Gbps |
| Security groups | Yes, plus network ACLs | No; network ACLs only |
| Source/destination check | You must disable it | Not applicable |
| Use as a bastion too | Possible (not recommended) | No |
| Cost | Instance hours + data transfer | Gateway hours + per-GB processing + data transfer |
Self-checkQuestion
Private instances must download updates from the internet but must never be reachable from it. The solution must be highly available and need no maintenance. What should you use?
#NAT gateways and high availability
A zonal NAT gateway is highly available inside one AZ, but if that whole AZ fails, the gateway fails with it. The rule for production:
- Create one NAT gateway in each AZ you use, each in that AZ’s public subnet.
- Give each AZ’s private subnets their own route table, pointing
0.0.0.0/0at the NAT gateway in the same AZ.
This avoids two problems with sharing a single NAT gateway:
- Single point of failure: if the AZ with the only NAT gateway fails, the surviving AZs lose internet access too.
- Cross-AZ data charges: every gigabyte from AZ B to a NAT gateway in AZ A is billed as inter-AZ transfer, on top of NAT processing.
You do not need cross-AZ failover for NAT: if an AZ fails, the servers that used its NAT gateway are gone too.
NAT gateways and Availability Zones
A zonal NAT gateway lives in one AZ. Compare one per AZ, one shared, and the Regional NAT gateway when an AZ fails.
Scenario
Route table AZ A: 0.0.0.0/0 → NAT A · Route table AZ B: 0.0.0.0/0 → NAT B
Each AZ has its own NAT gateway in its public subnet, and each AZ’s private route table points to the NAT gateway in the same AZ. Traffic never crosses AZs.
#Regional NAT gateways
Since November 2025, a NAT gateway can also be created in regional availability mode. A Regional NAT gateway is attached to the VPC rather than to a public subnet:
- one NAT gateway (one ID, one route target) serves every AZ of the VPC;
- AWS adds and removes AZs automatically as your workloads appear in them (expanding to a new AZ can take some time, up to about an hour);
- no public subnets are needed to host it, and it has its own route table;
- in automatic mode AWS also manages its public IP addresses; in manual mode you supply Elastic IPs.
It gives the resilience of “one per AZ” with far less to manage. Zonal NAT gateways remain available, and are still required for private NAT (below).
#Public vs private NAT gateways
NAT gateways have two connectivity types:
| Public NAT gateway | Private NAT gateway | |
|---|---|---|
| Created in | A public subnet | A private subnet |
| Elastic IP | Required | None |
| Internet gateway | Required | Not used |
| Used for | Private subnets → internet | Private subnets → other VPCs or on-premises networks through a transit gateway or virtual private gateway |
| Typical reason | Outbound internet | The other network overlaps your range, or only accepts traffic from a small allowed range |
A private NAT gateway translates your servers’ addresses into an address from a small, non-overlapping “routable” range of your VPC, so traffic can reach a network that overlaps with the rest of your range. It never touches the internet.
#Try it yourself
Create a NAT gateway for a private subnet (replace the IDs with yours; a NAT gateway costs money per hour, so delete it afterwards):
EIP=$(aws ec2 allocate-address --domain vpc --query AllocationId --output text)
NAT=$(aws ec2 create-nat-gateway --subnet-id $PUBLIC_SUBNET --allocation-id $EIP \
--query NatGateway.NatGatewayId --output text)
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT
aws ec2 create-route --route-table-id $PRIVATE_RT --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT
# From a private instance (via Session Manager), check which public address the internet sees:
curl -s https://checkip.amazonaws.com # prints the NAT gateway's Elastic IP
# Session Manager instead of SSH (needs the AWS CLI Session Manager plugin):
aws ssm start-session --target i-0123456789abcdef0
# Clean up
aws ec2 delete-nat-gateway --nat-gateway-id $NAT
aws ec2 release-address --allocation-id $EIP # after the NAT gateway is deleted
#Summary
Key takeaways
- A bastion host is an EC2 instance in a public subnet used to reach private servers. Its security group allows SSH/RDP only from admin IPs; the private servers allow SSH/RDP only from the bastion’s security group.
- Session Manager (or EC2 Instance Connect Endpoint) gives shell access with no inbound ports, no SSH keys and no bastion, controlled by IAM and fully logged: the exam’s answer to “without opening port 22”.
- NAT rewrites the source address outbound and keeps a translation table, so private servers can start connections out but nothing can start a connection in.
- A NAT instance needs a public subnet, an Elastic IP, routes pointing to it, and source/destination check disabled; it is self-managed and legacy.
- A NAT gateway is managed, 5–100 Gbps, in a public subnet with an Elastic IP, needs an internet gateway, has no security groups, and handles IPv4 only (IPv6 uses an egress-only internet gateway).
- For high availability use one NAT gateway per AZ with per-AZ route tables, or a Regional NAT gateway. One shared NAT gateway is a single point of failure and adds cross-AZ charges.
- A private NAT gateway (no EIP, no IGW) connects to other VPCs or on-premises networks with overlapping ranges.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
Engineers need shell access to instances in private subnets. Security requires no inbound ports open on any instance and a record of every session. What is the best solution?
Self-checkQuestion
A VPC uses two AZs with one NAT gateway in AZ A. Both AZs’ private route tables point to it. What happens if AZ A fails?
Self-checkQuestion
Private instances behind a NAT instance cannot reach the internet. The routes point to the NAT instance, which has an Elastic IP and is in a public subnet. What is the most likely cause?
Self-checkQuestion
Which statement best describes a bastion host?
Self-checkQuestion
A solutions architect is writing the inbound rule for a Linux bastion host’s security group. The admins connect from the office range 198.51.100.0/24. Which rule is correct?
Self-checkQuestion
What source should the private application servers’ security group allow for inbound SSH in a bastion design?
Self-checkQuestion
Why can’t a host on the internet start a connection to a private instance that uses a NAT gateway?
Self-checkQuestion
Which route must a private subnet’s route table contain for its instances to reach the internet through a NAT gateway?
Self-checkQuestion
What does the EC2 source/destination check do, and why does it break a NAT instance?
Self-checkQuestion
Which two statements about a NAT gateway are true?
Choose 2
Self-checkQuestion
Which two steps are required to make a NAT instance forward traffic for private subnets?
Choose 2
Self-checkQuestion
Which of the following is NOT a good practice for a bastion host?
Self-checkQuestion
A team wants to build a NAT instance today from the ready-made NAT AMI that AWS used to publish. What should the solutions architect point out?
Self-checkQuestion
An engineer wants to control which private subnets can send traffic through a NAT gateway and looks for its security group. What is correct?
Self-checkQuestion
A web server in the same public subnet as a NAT gateway has its own public IP. How does it reach the internet?
Self-checkQuestion
A company’s application servers in private subnets have IPv6 addresses and must open outbound connections to IPv6 hosts on the internet, while nobody on the internet may start a connection to them. What should the solutions architect use?
Self-checkQuestion
A NAT gateway shows Available in a public subnet that routes to the internet gateway, and it has an Elastic IP. Instances in a private subnet still cannot reach the internet. What is the most likely cause?
Self-checkQuestion
An engineer created a public NAT gateway in a subnet whose route table has only the local route, then pointed the private subnets’ 0.0.0.0/0 at it. Instances still cannot reach the internet. Why?
Self-checkQuestion
A NAT instance has its source/destination check disabled, an Elastic IP and correct routes. Its security group allows inbound SSH from the office only. Private instances cannot download packages over HTTPS. What fixes it?
Self-checkQuestion
A company’s NAT instance has become a bandwidth bottleneck, and the operations team is tired of patching it. Which change meets both needs with the least effort?
Self-checkQuestion
A company runs private subnets in three AZs but only one NAT gateway, in AZ A. Apart from resilience, what extra cost does this design create?
Self-checkQuestion
A company runs a web application in private subnets across three AZs. The servers download patches from the internet, and outbound access must survive the loss of any one AZ. The architect will use zonal NAT gateways. What should the architect do?
Self-checkQuestion
A VPC has a zonal NAT gateway in each of two AZs, with per-AZ route tables. AZ A fails. Which two statements are true?
Choose 2
Self-checkQuestion
A company wants a single NAT gateway that serves every AZ in its VPC, extends itself when workloads launch in a new AZ, and does not need public subnets. What should the solutions architect use?
Self-checkQuestion
Which two statements about a Regional NAT gateway are true?
Choose 2
Self-checkQuestion
A company’s VPC uses 10.0.0.0/16 and must send traffic through a transit gateway to an on-premises network that also uses 10.0.0.0/16. The workloads must not get public IP addresses. What should the solutions architect use?
Self-checkQuestion
Which two statements about a private NAT gateway are true?
Choose 2
Self-checkQuestion
Which of the following is NOT required to open a Session Manager session to a private EC2 instance?
Self-checkQuestion
A company runs instances in private subnets from a hardened image that cannot run the Systems Manager agent. Engineers must connect with SSH, authenticated through IAM, with no bastion host and no public IPs. What should the solutions architect use?
Self-checkQuestion
A security team requires shell access to private instances with no SSH keys, no inbound ports and no bastion host. Which two should the solutions architect configure?
Choose 2