DEV Community

Stefan Sundin for AWS Community Builders

Posted on • Edited on • Originally published at community.aws

How to configure a split-traffic VPN to access private S3 buckets

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"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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. :)

Billboard image

Use Playwright to test. Use Playwright to monitor.

Join Vercel, CrowdStrike, and thousands of other teams that run end-to-end monitors on Checkly's programmable monitoring platform.

Get started now!

Top comments (0)

Best Practices for Running  Container WordPress on AWS (ECS, EFS, RDS, ELB) using CDK cover image

Best Practices for Running Container WordPress on AWS (ECS, EFS, RDS, ELB) using CDK

This post discusses the process of migrating a growing WordPress eShop business to AWS using AWS CDK for an easily scalable, high availability architecture. The detailed structure encompasses several pillars: Compute, Storage, Database, Cache, CDN, DNS, Security, and Backup.

Read full post

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay