skip to Main Content

What I am trying to do is restrict access to a file to a single IP address.

The bucket policy belows works only when either 0.0.0.0/0 is used instead of the actual IP address or the condition is removed, otherwise a 403 (Forbidden) error is served.

The IP address is confirmed to be 68.6N.NN1.1N2.

I recieve a 200 response if I send a curl request via terminal. However, if I include a direct link to the object in index.php, the response is a 403 (Forbidden) error…

(I have zero experience with cloud platforms. Any help would be very much appreciated.)

{
    "Version": "2012-10-17",
    "Id": "Policy17NN310NN0610",
    "Statement": [
        {
            "Sid": "Stmt171NN106NN335",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::testbucket/file.jpg",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "68.6N.NN1.1N2"
                }
            }
        }
    ]
}

Screenshot Confirming the IP Address

IP Address Confirmation

Screenshot Showing a 200 Response to a cURL Request

Response to Terminal cURL Request

2

Answers


  1. The ‘preferred’ method would be:

    • Keep the Amazon S3 bucket private, with no Bucket Policy
    • Create an IAM User for the application running on the hosting server
    • Grant permissions to the IAM User to grant it access to the appropriate bucket and prefixes
    • The application uses an AWS SDK to access the file, or it constructs an Amazon S3 pre-signed URL, which provides time-limited access to private objects in Amazon S3

    This way, access is authenticated rather than relying on the request coming from a specific IP address, especially since that IP address is potentially shared with systems not under your control.

    Login or Signup to reply.
  2. From the comments, there is some confusion about how the S3 bucket policy interacts with the way the file is being accessed.

    User's Browser
          |
          v
    +------------+   request for file   +--------+    IP-based restriction    +----------+
    | index.php  | -------------------> | AWS S3 | <------------------------- |  cPanel  |
    | on Server  |    (client's IP)     | Bucket |    (server's IP allowed)   | Terminal |
    +------------+                      +--------+                            +----------+
    

    Expanding on jellycsc‘s comment, the issue could be with the IP address seen by AWS when a user tries to access the file through index.php on a website. AWS is seeing the IP address of the user’s browser, not the server’s IP address. Since the bucket policy is set to only allow access from a single IP address (the server’s), requests coming from any other IP address (like a user’s browser) will be denied with a 403 error.

    The fact that curl https://icanhazip.com/ returns the expected IP address suggests that your server is using the correct IP. But again, if index.php includes a direct link to the object and the browser tries to fetch it, AWS will see the request as coming from the client’s IP address, not the server’s.

    If you want the object to be accessible only from the server’s IP, you will need to make sure that the server itself fetches the object and then serves it to the client. That would involve a server-side script that handles the download and then serves the file to the client, rather than the client directly requesting the file from S3 (S3Client + S3.getObject()).

    <?php
    require 'vendor/autoload.php';
    
    use AwsS3S3Client;
    use AwsExceptionAwsException;
    
    $s3Client = new S3Client([
        'version' => 'latest',
        'region'  => 'your-region-1',
        // 'credentials' => // if needed, though it is better to use IAM roles
    ]);
    
    $bucketName = 'testbucket';
    $fileKey = 'file.jpg';
    
    try {
        // Get the object from S3
        $result = $s3Client->getObject([
            'Bucket' => $bucketName,
            'Key'    => $fileKey,
        ]);
    
        // Set appropriate header for the file content
        header("Content-Type: {$result['ContentType']}");
        header('Content-Disposition: attachment; filename="' . basename($fileKey) . '"');
        header('Content-Length: ' . $result['ContentLength']);
    
        // Output the file content
        echo $result['Body'];
    } catch (AwsException $e) {
        // Handle error accordingly
        echo "Error fetching file: " . $e->getMessage();
    }
    ?>
    

    Here, when a user requests index.php, the server itself requests the object from S3 using its AWS credentials, and then passes it on to the user, without exposing the direct link to S3. The bucket policy IP restriction should work as expected because AWS only sees the server’s IP address.


    All I want to do is get the S3 bucket to respect its own policy so that I can quickly test something… I might not even need/want to use AWS at the end of the day. But I do need to restrict by IP address alone.

    It is true, the above script bypasses IP-based restrictions entirely by using AWS SDK for PHP to access the file with IAM credentials.

    If you need to test IP-based access restrictions without involving IAM roles or AWS SDK authentication, you would need to make sure the IP address in the S3 bucket policy is correct and that requests to S3 are actually coming from that IP address.

    And… you might already have conducted the test regarding IP-based restrictions through direct links in index.php. A 403 Forbidden error when accessing the S3 object through a web page—accurately reflects the situation where the S3 bucket policy restricts access to a specific IP address (presumably the server’s), and the requests come from different client IP addresses through the browser.

    So that confirms the behavior expected under such a policy configuration: direct access attempts from any IP address other than the one specified in the policy will result in access being denied.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search