I'm in the process of creating an SFTP only Docker container, one that will be used by multiple people for the sole purpose of uploading and managing files in their own chrooted Environment.

On paper, it's pretty secure: I'll disable every form of bash login, and I won't run any other process in it. However I would like to harden it just a little bit more:

I want to prevent this container from accessing the Internet from the inside, except for it's purpose of being an SFTP server.

To make things clear: I know how to prevent the outside world from accessing my container - I can setup incoming iptables rules, and I can expose only the SFTP port in my docker run command.

However I would like to make the following command (as an example) fail, when ran inside the container:

curl google.com

My intention is to diminish the amount of damage that a hacked container can do (not being able to be used to send spam email, etc).

  • There are a couple pending feature requests that can help with this type of stuff. #6743 which would let you pre-create iptables rules on the host before the container is started, and #6982 which would let you add iptables rules when the container starts. – Patrick Sep 28 '14 at 8:17
  • Docker gives you full control over a container's network interfaces; see How Docker networks a container. For example, setting the --net=none flag on docker run will disable all external network adapters, enabling you to add your own and customize network traffic rules. – sffc Jan 11 '16 at 10:48

It still makes sense to put some ingress rules inside your docker instance to help ward off attacks, but you will have to limit outbound (Internet) access from whatever upstream router the docker image connects with. The reason for this is, if you try to block outbound access with the firewall rules inside your instance, then if the instance is compromised those rules could be removed by the attacker. By blocking egress via the instance's router, you block outbound access even in the event of a compromise - the attacker would have to compromise the router as well.

Ok, so after receiving some commentary that explains that the filtering was intended for the container's host, it's a little clearer what is trying to be accomplished. In which case, on the host, you would add some rules similar to this:

iptables -A FORWARD -s lo.cal.sub.net -d con.tai.ner.ip -j ACCEPT
iptables -A FORWARD -s con.tai.ner.ip -d lo.cal.sub.net -j ACCEPT
iptables -A FORWARD -s ! lo.cal.sub.net -d con.tai.ner.ip -p tcp --dport sftp -j ACCEPT
iptables -A FORWARD -s con.tai.ner.ip -d ! lo.cal.sub.net -p tcp --sport sftp -j ACCEPT
iptables -A FORWARD -s con.tai.ner.ip -m state --state related,established -j ACCEPT
iptables -A FORWARD -s con.tai.ner.ip -j DROP

The first two rules are for access between the host and the container. The third rule says (roughly) that anything that isn't the host's subnet headed for SFTP is just OK by us; the fourth is the outbound rule that is basically a twin to the third; the fifth rule is a catch-all (in case there are other related ports that are used), although it shouldn't be needed, you could probably remove it; the last rule is the magic on that prevents access to anything other than the host subnet. Because access is given in the first few rules, it will never trigger unless none of the preceding rules apply, in which case we are saying "we don't care what you want, you didn't match anything you're approved for, so you can't get there from here". Inbound traffic from the outside will be satisfied by the 3rd and 4th rules.

  • Interesting downvote, given that there is no way to perform this inside the container without having absolute trust in the contents of the container. – Avery Payne Sep 29 '14 at 17:59
  • The docker container's upstream router (assuming the default most supported configuration) is the host on which it is running, and we are looking for a way disable a single container's Internet access on that host (not inside the container) while not breaking other docker functionality. – Tarnay Kálmán Oct 2 '14 at 0:55
  • (sigh) I really shouldn't re-write my answers while on just 6 hours of sleep. I've amended the answer given. – Avery Payne Oct 2 '14 at 1:19
  • Docker (assuming the default most supported configuration) publishes container ports on the host via its userspace tcp proxy, so I am not sure if the forwarding chain is even relevant for the rules concerning the sftp service. – Tarnay Kálmán Oct 2 '14 at 2:06
  • Guess I'll have to set up a test environment and haul out Docker, and see what's involved. It sounds like you're suggesting the rules should be moved from forward to input. – Avery Payne Oct 2 '14 at 18:03

This isn't really a docker specific problem. There are a couple of ways you could solve this.

  1. Use stateful iptables rules to allow connections inbound and related/established traffic then block everything else.

  2. Use an sftp only service such as ProFTPD that is incapable of running a shell.

In general, if you don't allow your users to get a shell and don't allow them to run programs from within the container, you don't need to worry about it.

  • 1.) Docker sets up some rules on its own by default, and appending to them would do nothing as there is a catch-allish rule in place already, and prepending would break existing functionality (such as links) if one is not careful, so it's not that trivial. 2.) Does not answer the question. And OP already set it up like that. Also, my use case is different. – Tarnay Kálmán Oct 4 '14 at 23:59

This is just a quick brainstorm, and I have not tested it yet. You will want to vet it in the lab before taking it to production.

To prevent outbound traffic on non-SSH (SFTP) and Web ports, you may want to apply policy via IPTABLES or another Layer4 firewall to DROP or REJECT traffic sourced from the segment used by docker containers destined to except when Destination Port is TCP22.

To solve the going-to-unapprove-places-on-the-web problem, you might want to try setting up an instance of a filtering/caching proxy, such as squid or bluecoat, which is listening on interface docker0 and which is using the host's defalt route to get out to the internet. From there, you could apply policy based on many criteria, as well as saving network utilization by caching static content. You might want to use NAT (I think IPTABLES and Masquerade provide this in Linux) on the host machine to enforce use of the proxy transparently (I described this in my response to I want to proxy only HTTP but I'm not sure what to do with HTTPS traffic). This implies have a reason to go onto the web in the first place that is in adherence with your company's policies.

Because of the nature of SSH (on which SFTP is based), you will not be able to provide interdiction of traffic for file-moving unless you implement a policy whereby containers may only use key-pairs provided by you. This is good for you, because it gives you some "I had no visibility or control over transferred files" defense if one of your customers transfers something illegal (such as IP infringement, or uses your service to exfiltrate information carrying a classification label, or they trade in CP), if you are brought to court for something your customers do (think analagous to common-carrier status for telcos). This is bad for you because you cannot cache frequently re-transferred, unchanged files, and because any policy you write into the contract with your customers will be essentially unenforceable through technical means.

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.