Every server instance with publicly facing IP address is constantly targeted by malicious network scanning bots. Those bots are usually harmless but they can always start a DDoS attack or discover a vulnerability. Additionally, they are obfuscating the SSH access logs and using up some of the server resources. In this tutorial, I will explain how to hide your AWS EC2 server from those scanners using IPv6. Internet Protocol version 6 addresses range is ~7.9×1028 times larger than IPv4, so in practice, it’s currently not targeted by bots.
We’ll deep dive into AWS VPC and security groups configuration to limit SSH access to IPv6 clients only. Some knowledge of AWS is required to complete this tutorial, but I will link to the complementary resources.
Let’s start by checking whether the bots are really knocking on your doors.
SSH access logs
You can check how often your server is targeted by scanner bots by SSHing into it and running these commands:
/var/log/auth.logis the default SSH log file for Ubuntu systems
you should see the similar output:
Bot login attempts are failing in the
preauth phase because they are using passwords, and your server is configured only to accept public/private key based logins.
If you’ve enabled password authentication to your server by adding this line to
you could also see a similar output:
Unless absolutely necessary enabling password-based login should be avoided.
If you don’t see any output, looks like your server if currently not targeted. It was not the case for my AWS EC2 instances. All of them started receiving unwanted visitors just minutes after provisioning.
AWS Guard Duty
You can also get a high-level overview of unauthorized access attempts using AWS Guard Duty.
As you can see, my servers are currently receiving a couple dozen “pings” a day.
Enable SSH access via IPv6
By default, the newly provisioned EC2 instances have an IPv4 public IP. We will need to reconfigure our default Virtual Private Cloud to enable SSH (port 22) access only via IPv6 address. HTTP (port 80) and HTTPS (port 443) will still be available via both IPv4 and IPv6, but I will describe options for securing them later.
Check out the official AWS docs about adding IPv6 for a more detailed guide. Below I describe steps necessary to add IPv6 to the default VPC and an already provisioned EC2 instance.
Adding IPv6 to the default VPC
You need to start by going to the VPC section of the AWS console. Next, choose Your VPCs and select Actions > Edit CIDRs for your default VPC. Now click on Add IPv6 CIDR.
Next, you need to reconfigure your subnets. You should check which subnet your provisioned EC2 instance belongs to, or add IPv6 CIDR for all of them. Depending on the region, you might have two or more default subnets.
Choose your subnet, select Actions > Edit IPv6 CIDRs than Add IPv6 CIDR.
Last component that you need to configure is a route table. Select Route Tables, choose your default route table, and click Actions > Edit Routes. Now you need to add a wildcard IPv6
::/0 destination targeting the same internet gateway as your default IPv4
0.0.0.0/0 destination. It will enable public internet access to associated subnets for all IPv6 clients.
Configure EC2 instance IPv6
Now go back to EC2 console. In the Instances section, select your instance and choose Actions > Networking > Manage IP Addresses. If you performed the VPC configuration correctly, you should now be able to assign a public IPv6 address to your instance.
Now we need to configure the security groups to only allow SSH access for IPv6 clients and HTTP for IPv4 and IPv6.
To do it, go to the Security Groups tab, click Create Security Group, and configure your security group. Check out the image below for a sample config. It might differ depending on your particular use case. The important part is to open port 22 only for IPv6
Ideally, I would like to whitelist only my own IPs in the security group. Unfortunately, it is impossible because my internet service provider does not offer a static IP. Also, if I wanted to access my server when traveling, then every time I would need to reconfigure the security group.
The last step is to assign our new security group to the EC2 instance. You can do it by going back to the EC2 tab, selecting your instance, and clicking Actions > Networking > Change Security Groups.
That’s it! Now your EC2 instance can only be accessed via its IPv6 address, effectively hiding it from SSH network scanning bots.
Protect HTTP ports with Cloudflare’s Bot Fight Mode
If you are running a publicly accessible web server, then hiding HTTP ports in IPv6 random address space is not the best idea. It has to be discoverable by HTTP clients, both good and malicious ones.
I use Cloudflare as a DNS provider. Recently they’ve introduced a free Bot Fight Mode. Enabling it should eliminate many of HTTP scanner bots.
One loophole that remains are HTTP scanner bots that might directly target your AWS instance IP, bypassing the Cloudflare’s proxy. You can check out this blog post for an elegant solution on how to cut them off using a custom security group dynamically updated via Lambda function.
Disadvantages and alternative to IPv6 based solution
If you want to access the server when traveling you are dependent on your internet providers to support an IPv6, but it should only be getting easier as the adoption increases.
It’s still security by obscurity, so it does not replace the need for following other security best practices.
Alternative solution could be a AWS Sessions Manager but it is not compatible with git-based Dokku deployments I am using for this blog and Abot. Other problem of this approach is that you can no longer simply SSH into your server but always need an AWS CLI installed.
Using a vast IPv6 address poll to hide your server from unwanted guests is a technique that’s worth considering for some use cases. Scanner bots are prevalent and potentially harmful, so cutting them off in advance might save you troubles down the road.