How do I get boto to work with port 443 being prerouted to another port?

adzuci asked:

My title may be poorly worded, but I’ll try to get the backstory straight:

I have Ubuntu instances with clusters of Docker containers all hosting web servers

In order to appease firewalls we want to use port 443 instead of port 8000 (where a service is listening for traffic and keeping track of sockets open to the appropriate containers)

To do this we added a rule:

sudo iptables -t nat -D PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8000

However the containers use boto to push content to s3 i.e. something like:

from boto.s3.connection import S3Connection

s3_connection = S3Connection(
s3_bucket = s3_connection.get_bucket(

With the prerouting rule in place boto can no longer use port 443 & returns with:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/local/lib/python2.7/dist-packages/boto/s3/", line 496, in get_bucket
    return self.head_bucket(bucket_name, headers=headers)
  File "/usr/local/lib/python2.7/dist-packages/boto/s3/", line 543, in head_bucket
    response.status, response.reason, body)
boto.exception.S3ResponseError: S3ResponseError: 405 Method Not Allowed

Without the rule boto works fine, but we can’t use port 8000 for a production ssl service.

How should we be configuring our PREROUTING table and service to do both things?

I’m not an expert on boto, iptables or docker, and it is interesting that this seems to be an issue on the containers and not the host.

My answer:

Your DNAT rule is not specific enough. It is applying to all traffic being forwarded through the host to port 443, regardless of origin or destination.

To resolve the problem, make the rule more specific, such as by specifying that it applies only to inbound traffic from the outside world. If this arrives on the eth0 interface, then you would add -i eth0 to the rule:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8000

This won’t apply to traffic going the other direction, where the “inbound” interface is e.g. docker0 and the “outbound” interface is eth0.

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.