Skip to content

Time Out on Windows with VPN DNS Override #7319

@sedlund

Description

@sedlund

Checkboxes for prior research

Describe the bug

Bug Report: @aws-sdk/client-s3 Times Out on Windows with VPN DNS Override

Is this a bug report or a feature request?
Bug Report

Package Name:
@aws-sdk/client-s3

SDK Version:
"@aws-sdk/client-s3": "^3.883.0"

Node.js Version:
v24.7.0

OS:
Windows 11

Describe the bug

The @aws-sdk/client-s3 client fails to establish a network connection and times out when running on Windows under a specific network configuration created by common VPN clients like Tailscale. The failure occurs when the VPN is configured to override the system's DNS servers but is not routing all traffic through a full tunnel (i.e., no "exit node" is active).

Image

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

@aws-sdk/[email protected]

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v24.7.0

Reproduction Steps

  1. Set up the Environment:

    • OS: Windows 11
    • Node.js: v24.7.0 or similar.
    • VPN Client: Install a client that can override system DNS, such as Tailscale.
  2. Configure the Failing Network State:

    • Connect the VPN client.
    • Enable the feature that forces all system DNS queries to go through the VPN's specified nameservers.
    • Crucially, ensure that an "exit node" or "full tunnel" is disabled. Only DNS traffic should be captured by the VPN's virtual adapter.
  3. Prepare the Reproducer Script:

    • Create a new directory.
    • Run npm init -y.
    • Run npm install @aws-sdk/client-s3.
    • Create a file reproduce-bug.js with the code below.
  4. Run the Test:

    • Execute node reproduce-bug.js. The script will time out.
    • For validation, disable the VPN's DNS override feature and run the script again. It will succeed immediately with an authentication error.

Logs

Failing Case (VPN DNS Override Enabled):

Attempting to make a request using the AWS S3 SDK...
Creating S3 client...
S3 client created.
Sending GetObjectCommand to S3 endpoint...

--- TEST FINISHED WITH AN ERROR ---
Error Name: TimeoutError
Error Message: The request timed out.

CONCLUSION: NETWORK FAILURE! BUG REPRODUCED!
The script failed to establish a connection with the server. This indicates a low-level networking issue in the SDK.

Working Case (Standard Network / VPN DNS Override Disabled):

Attempting to make a request using the AWS S3 SDK...
Creating S3 client...
S3 client created.
Sending GetObjectCommand to S3 endpoint...

--- TEST FINISHED WITH AN ERROR ---
Error Name: InvalidAccessKeyId
Error Message: The AWS Access Key Id you provided does not exist in our records.

CONCLUSION: NETWORK SUCCESS!
The script successfully connected to the server, which correctly rejected the dummy credentials.

Minimal Reproducer Code (reproduce-bug.js)

// Minimal reproducer for a network failure in the AWS SDK v3 client
// when operating under specific VPN DNS configurations on Windows.

const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');

// --- Configuration ---
// These details point to a public Backblaze B2 bucket.
const BUCKET_NAME = 'mybucket33';
const OBJECT_KEY = 'info.json';
const ENDPOINT_URL = 'https://s3.eu-central-003.backblazeb2.com';
const REGION = 'eu-central-003';

async function main() {
  console.log('Attempting to make a request using the AWS S3 SDK...');

  const s3Client = new S3Client({
    region: REGION,
    endpoint: ENDPOINT_URL,
    forcePathStyle: true,
    credentials: {
      // Dummy credentials are used intentionally.
      // A successful network connection should result in an "InvalidAccessKeyId" error.
      // A timeout or generic network error indicates the bug has been reproduced.
      accessKeyId: 'DUMMY_KEY_ID',
      secretAccessKey: 'DUMMY_SECRET_KEY',
    },
  });

  console.log('Sending GetObjectCommand to S3 endpoint...');
  const command = new GetObjectCommand({
    Bucket: BUCKET_NAME,
    Key: OBJECT_KEY,
  });

  try {
    // Set a reasonable timeout for the request.
    const response = await s3Client.send(command, { requestTimeout: 15000 });
    console.log('UNEXPECTED SUCCESS: The server responded. Status:', response.$metadata.httpStatusCode);
    console.log('\nCONCLUSION: NETWORK SUCCESS!');
  } catch (error) {
    console.error('\n--- TEST FINISHED WITH AN ERROR ---');
    console.error('Error Name:', error.name);
    console.error('Error Message:', error.message);

    if (error.name === 'InvalidAccessKeyId' || error.name === 'SignatureDoesNotMatch' || error.name === 'AccessDenied') {
      console.log('\nCONCLUSION: NETWORK SUCCESS!');
      console.log('The script successfully connected to the server, which correctly rejected the dummy credentials.');
    } else {
      console.log('\nCONCLUSION: NETWORK FAILURE! BUG REPRODUCED!');
      console.log('The script failed to establish a connection with the server. This indicates a low-level networking issue in the SDK.');
    }
  }
}

main();

Observed Behavior

Current behavior

The S3 client send() command hangs for the duration of the request timeout and then fails with a TimeoutError. No connection is ever established with the server.

Expected behavior

The S3 client should successfully establish a network connection to the S3 endpoint, regardless of which network interface handled the DNS resolution. Given dummy credentials, the expected behavior is a fast failure with an authentication error from the server (e.g., InvalidAccessKeyId).

Possible Solution

No response

Additional Information/Context

When configuring Tailscale to use an Exit node (the full default route goes through the VPN) the S3 connection works.

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.p2This is a standard priority issuethird-partyThis issue is related to third-party libraries or applications.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions