If you maintain a VPN that allows users to access private VPC resources, then you might also want to use it to allow access to private S3 buckets. This post will help you configure your VPN accordingly.
This is only relevant if your VPN configuration is splitting the traffic in a way where only part of the traffic goes through the VPN. If you route all of the user's network traffic through the VPN then this post doesn't apply to your use case.
If you have a VPC Interface Endpoint set up (with private DNS enabled), then likewise this is should not be an issue. However, since interface endpoints cost $0.01/per AZ/per hour, I prefer using Gateway Endpoints since they are FREE and can even lower your AWS bill.
Now that we have defined the specific use case when this applies, please join me in figuring out what IP ranges you need to configure to be sent through the VPN.
Your bucket policy should look something like this (taken from this documentation page):
{
"Version": "2012-10-17",
"Id": "Policy1415115909152",
"Statement": [
{
"Sid": "Access-to-specific-VPCE-only",
"Principal": "*",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["arn:aws:s3:::awsexamplebucket1",
"arn:aws:s3:::awsexamplebucket1/*"],
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "vpce-1a2b3c4d"
}
}
}
]
}
As mentioned in my other post, Four surprising IPv6 gotchas with Amazon S3, you may also want to add a NotIpAddress
to the condition to allow for access over IPv6. Here's what that would look like (replace the IPv6 CIDR range with the CIDR range for your own VPC):
{
"Version": "2012-10-17",
"Id": "Policy1415115909152",
"Statement": [
{
"Sid": "Access-to-specific-VPCE-only",
"Principal": "*",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["arn:aws:s3:::awsexamplebucket1",
"arn:aws:s3:::awsexamplebucket1/*"],
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "vpce-1a2b3c4d"
},
"NotIpAddress": {
"aws:SourceIp": "2600:1234:abcd:800::/56"
}
}
}
]
}
With this in place, you are now required to route the traffic through your VPN to access this S3 bucket.
In this example I am configuring a WireGuard VPN client config using the AllowedIPs
setting. This might look like the following to send both IPv4 and IPv6 traffic through to the VPN:
AllowedIPs = 10.0.0.0/8, 2600:1234:abcd:800::/56
However, since we're using a VPC Gateway Endpoint, we need to manually configure the IP ranges that Amazon S3 use here as well. Amazon publishes an ip-ranges.json file that makes it easy to automate some of this work.
Start by downloading the ip-ranges.json
file:
curl -O https://ip-ranges.amazonaws.com/ip-ranges.json
My S3 bucket and VPC are both located in us-west-2, so I can use these jq
commands to retrieve the IP ranges that are appropriate for me:
$ cat ip-ranges.json | jq -Mr '.prefixes[] | select((.service == "S3") and (.region == "us-west-2")) | .ip_prefix' | sort
18.34.244.0/22
18.34.48.0/20
3.5.76.0/22
3.5.80.0/21
35.80.36.208/28
35.80.36.224/28
52.218.128.0/17
52.92.128.0/17
$ cat ip-ranges.json | jq -Mr '.ipv6_prefixes[] | select((.service == "S3") and (.region == "us-west-2")) | .ipv6_prefix' | sort
2600:1f68:4000::/39
2600:1fa0:4000::/39
2600:1ff0:4000::/39
2600:1ff8:4000::/40
2600:1ff9:4000::/40
2600:1ffa:4000::/40
All you need to do is add all of these IP ranges to your AllowedIPs
list. Here is what it looks like for me:
AllowedIPs = 10.0.0.0/8, 2600:1234:abcd:800::/56, 18.34.244.0/22, 18.34.48.0/20, 3.5.76.0/22, 3.5.80.0/21, 35.80.36.208/28, 35.80.36.224/28, 52.218.128.0/17, 52.92.128.0/17, 2600:1f68:4000::/39, 2600:1fa0:4000::/39, 2600:1ff0:4000::/39, 2600:1ff8:4000::/40, 2600:1ff9:4000::/40, 2600:1ffa:4000::/40
With these changes, my VPN configuration allows me to access both my private VPC resources and my private S3 buckets. It's a little bit messy, but it works!
If you have experience in how this is simplified using a VPC Interface Endpoint, please let us know in the comments. It would be an interesting read.
Please let me know if this helped you, or if anything needs clarification. :)