AWS / Guide 5
Firewalls, endpoints and admin access
Outbound control, Network Firewall, WAF and Shield, VPC endpoints, S3 Block Public Access, and Session Manager instead of SSH and RDP.
Security groups filter by address and port, and that's all they do. They can't allow *.amazonaws.com and block the rest of the internet, they don't inspect traffic, and they don't stop an S3 bucket from being public. This guide covers the layers around them: controlled outbound, AWS Network Firewall, AWS WAF, Shield, VPC endpoints, S3 Block Public Access, and getting to servers without opening SSH or RDP.
What sits where
| Control | Protects against | Works at |
|---|---|---|
| Security groups and NACLs | Unwanted connections between addresses and ports | Interface and subnet (layer 4) |
| AWS Network Firewall | Uncontrolled outbound, traffic between VPCs, known-bad destinations | Inspection VPC or subnet, traffic routed through it |
| AWS WAF | Attacks on websites and APIs: SQL injection, cross-site scripting, bots | CloudFront, Application Load Balancer, API Gateway |
| AWS Shield | DDoS floods | Public endpoints |
| VPC endpoints (PrivateLink) | Traffic to AWS services crossing the internet | The VPC's route to the service |
| S3 Block Public Access | Buckets and objects made public by mistake | Account and bucket |
| Session Manager, EC2 Instance Connect Endpoint | Open SSH and RDP | Admin access to instances |
Control outbound traffic
In AWS, a subnet is "public" if its route table sends 0.0.0.0/0 to an internet gateway, and instances there need a public IP to use it. Everything else is private, with no way out, until you add one:
- NAT gateway in a public subnet, with private subnets routing
0.0.0.0/0to it. Fixed Elastic IPs that partners can allow-list, no inbound exposure. Put one in each Availability Zone for production; one shared across AZs saves money but creates a single point of failure and cross-AZ charges. - Egress-only internet gateway for IPv6: outbound allowed, inbound refused.
- A central egress VPC behind a Transit Gateway, with NAT gateways and Network Firewall, when many VPCs need the same outbound control. Fewer NAT gateways, one place to inspect.
Don't give instances public IPs just so they can download updates. AWS also charges for every public IPv4 address, in use or not, which makes the habit more expensive than it used to be. VPC Block Public Access can turn off internet gateway traffic for a whole region or for chosen VPCs in one setting.
AWS Network Firewall
Network Firewall is a managed, stateful firewall you place in its own subnets, with route tables sending traffic through it. Its main advantage over security groups is filtering outbound traffic by domain name (allow .amazonaws.com and your update servers, deny everything else) and Suricata-compatible intrusion prevention rules, including AWS-managed threat signature groups.
- Put it where traffic converges: the central egress or inspection VPC in a hub-and-spoke design. One per workload VPC gets expensive quickly.
- Use stateful rule groups with strict order and a default drop at the end, so the rule order is the order you read.
- Send alert and flow logs to CloudWatch Logs or S3. A dropped connection with no log is the hardest problem to troubleshoot.
- TLS inspection is available when you need to see inside encrypted traffic, with the certificate management that comes with it.
For outbound DNS filtering alone, Route 53 Resolver DNS Firewall is much cheaper: it blocks lookups of domains on AWS-managed threat lists or your own lists, for every VPC it's associated with.
AWS WAF and Shield
Any website or API on the internet should sit behind AWS WAF, on CloudFront (global) or the Application Load Balancer or API Gateway (regional). Start with the AWS managed rule groups: the core rule set, known bad inputs, the one for your stack (SQL database, Linux, Windows, PHP), and the IP reputation list. Add rate-based rules to limit requests per client, and Bot Control where scraping or credential stuffing is a problem.
Run new rules in Count mode for a week or two, review what would have been blocked in the WAF logs, add scope-down statements for the false positives, then switch to Block. And make sure traffic can't go around the WAF: the load balancer's security group should accept only CloudFront's managed prefix list, not 0.0.0.0/0.
Shield Standard protects every AWS customer against common network and transport-layer DDoS attacks at no cost. Shield Advanced adds protection tuned to your resources, the AWS Shield Response Team, WAF at no extra charge for protected resources, and cost protection for scaling during an attack. It's a significant annual commitment per organisation, so it suits internet-facing services where downtime is expensive.
VPC endpoints for AWS services
Without endpoints, an instance in a private subnet reaches S3, Systems Manager or Secrets Manager through the NAT gateway, over public endpoints, paying NAT data processing on the way. VPC endpoints keep that traffic inside AWS:
| Gateway endpoint | Interface endpoint (PrivateLink) | |
|---|---|---|
| Services | S3 and DynamoDB only | Most AWS services, and partner and your own services |
| How it works | A route in the subnet route tables | A network interface with a private IP in your subnet |
| Reachable from on-premises | No | Yes, over VPN or Direct Connect |
| Cost | Free | Per endpoint per AZ per hour, plus data processed |
| Use for | Always, in every VPC that uses S3 or DynamoDB | Services called often or holding sensitive data: SSM, Secrets Manager, KMS, ECR, CloudWatch Logs |
Endpoint policies limit what can pass through, for example only buckets in your own organisation. On the other side, bucket policies with aws:SourceVpce or aws:SourceVpc conditions make sure a bucket is only reachable through your endpoints. Interface endpoints use private DNS, so the normal service name resolves to the private IP inside the VPC; share them across VPCs from a central network account with Route 53 private hosted zones.
S3 Block Public Access
New buckets have Block Public Access on and ACLs disabled by default, and objects are encrypted with SSE-S3 by default. Older buckets may not be. Set Block Public Access at the account level in every account, so no bucket can be made public, and serve genuine public content through CloudFront with origin access control instead of a public bucket.
# Account-level Block Public Access (S3 Control)
$account = (Get-STSCallerIdentity).Account
Get-S3CPublicAccessBlock -AccountId $account
# Turn all four settings on for the account
Add-S3CPublicAccessBlock -AccountId $account -PublicAccessBlockConfiguration_BlockPublicAcl $true `
-PublicAccessBlockConfiguration_IgnorePublicAcl $true -PublicAccessBlockConfiguration_BlockPublicPolicy $true `
-PublicAccessBlockConfiguration_RestrictPublicBucket $true
Get-AwsS3PublicAccessReport.ps1 checks every bucket's Block Public Access settings, whether its policy is public, and its encryption and versioning.
Admin access without open ports
SSH and RDP should never be open to the internet. AWS has two ways to manage instances without it:
Systems Manager Session Manager opens a shell or PowerShell session through the SSM Agent, which connects out to Systems Manager. The instance needs no inbound rule, no public IP and no SSH keys; it needs the agent (preinstalled on most AWS AMIs), an instance profile with AmazonSSMManagedInstanceCore, and a route to Systems Manager (NAT or the ssm, ssmmessages and ec2messages interface endpoints). Access is controlled by IAM, sessions can be logged to S3 or CloudWatch Logs, and port forwarding covers RDP:
# Shell session (requires the AWS CLI and the Session Manager plugin)
aws ssm start-session --target i-0123456789abcdef0 --profile notes-test
# RDP through Session Manager: connect your RDP client to localhost:13389
aws ssm start-session --target i-0123456789abcdef0 --document-name AWS-StartPortForwardingSession `
--parameters 'portNumber=3389,localPortNumber=13389' --profile notes-test
EC2 Instance Connect Endpoint lets you SSH or RDP to instances in private subnets, with no agent and no public IP, through an endpoint in the VPC. The instance's security group allows 22 or 3389 from the endpoint's security group only. Use it for instances that can't run the SSM Agent, such as some appliances.
Fleet Manager in the Systems Manager console adds a browser-based RDP session on top of Session Manager, which is useful when a Windows admin can't install the CLI.
Examples to try
From aws.ravindran.in: NAT gateway, egress-only internet gateway, gateway endpoint, interface endpoint, S3 bucket policies and ACM with an Application Load Balancer.