How to restrict access to service via iptables?


Hi there,

I have a service running through Rancher. I have port 13001 on my host being forwarded to port 8080 in my service. This all works fine, and I can access my service by going to port 13001 on my server in my browser.

The problem is, I can do that anywhere. I want to lock it down so I can only access this service from certain IP addresses. I’ve tried playing with iptables a lot and haven’t really gotten anywhere with it, past just completely blocking all access to my service and any other service I have.

I understand that this isn’t a directly Rancher related question, but, it’d be great to know how to do this, and also maybe make it an option in Rancher somehow even.

Restricting access to exposed services

@SeerUK looks like you need to add a rule like:

sudo iptables -t mangle -A PREROUTING \! --src <source cidr> -m tcp -p tcp --dport <your port> -j DROP

This rule will drop all the requests that are NOT coming from a specific source cidr to the destination port. The rule should be added to the mangle pre-routing chain, so its hit before routing rules are applied.


Thanks Alena, that makes sense, I’ll give it a shot tonight.


Okay, that works (thank you!), I just have one more question. Would it be possible to make it so that all services were completely blocked by default, and had to be specifically allowed, instead of the other way around?


Glad the workaround worked. Regarding being blocked by default - we are keeping consistent with the default docker behavior for container ports- once the port is published, its available by default to everyone accessing the host. It works this way in standalone container case as well as service’s containers.

You can “kind of” achieve your desired behavior by creating a load balancer listing on your application public port (and not publishing the port on the target service itself). Once you decide that your service is ready for access, register it to the LB service, and all the traffic would get forwarded to your target service. But even in this case, you can’t really limit traffic based on source ip.


Okay, cool - thanks for the help! :smile:


Alena’s command was displayed mangled by the forum software… fixed now.

It should be possible to add rules to ALLOW specific IP/CIDR and/or ports to the PREROUTING chain, then add a final rule that DROPs anything else (perhaps only if coming from the public ethernet interface(s)).

Something like (totally untested, professional stuntman, do not attempt, offer void in Tennessee):

# Allow anything from
iptables -t mangle -A PREROUTING --src -j ACCEPT 
# Allow anything to port 80
iptables -t mangle -A PREROUTING -m tcp -p tcp --dport 80 -j ACCEPT
# Drop anything else coming from eth0
iptables -t mangle -A PREROUTING -i eth0 -j DROP


This is really close to what I want, but I think that last rule is a little too much, and stops a lot of stuff from working. This is a great crash course in iptables though! :smiley:


Well you said completely blocked by default :wink:

Yes more practically you probably want to not restrict things like ICMP, outbound requests or replies to established connections and such. Any basic iptables tutorials on the intetnets should help you get the rules describing what you want, plus -t mangle -A PREROUTING to get them in the right part of the processing. The key thing is the first matching rule wins and you want what’s left to be dropped at the last rule.


Just as an update to this, in case anybody else comes across this and isn’t experienced with iptables already like myself, this is the end ruleset that I used (it’s actually a lot more than the following, for multiple ports, and allowing many more hosts):

iptables -t mangle -A PREROUTING --src <source IP> -m tcp -p tcp --dport <destination port> -j ACCEPT
iptables -t mangle -A PREROUTING --src <source IP> -m tcp -p tcp --dport <destination port> -j ACCEPT
# Above rules to allow specific IP / subnet
iptables -t mangle -A PREROUTING -m tcp -p tcp --dport <destination port> -j DROP
# Above to block anything above not defined, just to that specific port

I have it all working perfectly now, I’ll just have to remember to block ports when I add new services to the host!


I understand why you would keep this as the default, but docker lets you Disable this functionality with the --iptables=false flag. Is this something that is available in Rancher as well?


Just a thought regarding using the MANGLE chain for filtering:
You are strongly advised not to use this table for any filtering; nor will any DNAT , SNAT or Masquerading work in this table.
Why would rancher make you use the mangle chain, after all, when the PREROUTING rule could easily be changed to allow a package coming only from a certain (or several) IP? It doesn’t make any sense. Unless, of course, Rancher is going to recreate the rules in the iptables over and over leaving you with no other option…


If you disable docker functionality of managing iptables, then Rancher will also not manage your iptables, and you can manipulate the rules however you want to. (this is, of course the behaviour for Rancher 1x, not Rancher 2, which is based on kuberentes)