On March 27, 2011 12:21 , Mark Montague <mark(a)catseye.org> wrote:
The requirements are:
1. Allow httpd to serve any requests on ports 80 and 443 from any
2. Allow httpd and its scripts (CGIs) to access any resource (databases,
back-end content web servers, etc.) on the local machine via the
3. Prohibit any other traffic from httpd. Specifically, do not allow
any access by either httpd or its scripts to resources on remote
4. Do not affect any other service or user running on the machine.
I haven't been able to solve the problem by labeling interfaces, yet --
requirement 1 keeps getting in my way.
However, I was able to solve the problem by labeling packets.
I was also able to solve the problem another way, using a netfilter
This has the advantage
of allowing more flexible action than just an AVC denial (for example,
sending a TCP reset to get a script such as curl to immediately give up
and exit). But it is a horrible, hacky solution that brutalizes the
SELinux LSM, is extremely fragile, and probably should not exist -- I'd
like to apologize for that right now. But I thought it would be a
useful thing to present for the sake of academic discussion.
Here are the commands (no local policy is needed, if you don't count the
setsebool -P httpd_can_network_connect=on
# Allow loopback device traffic to/from all services or users:
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Accept incoming web server traffic:
iptables -A INPUT -p tcp -m multiport --dports 80,443 \
-m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Silently block all other incoming traffic:
iptables -A INPUT -j DROP
# httpd is already allowed (by the rules above) to send any traffic
# via the loopback device in order to access various local resources.
# Also allow httpd to respond to incoming web server traffic (for
# which we've already accepted the input, above). Prohibit httpd
# from sending any other outbound traffic.
iptables -N HTTPD_OUT
iptables -A OUTPUT -m selinux --task-ctx system_u:system_r:httpd_t:s0 \
iptables -A HTTPD_OUT -m conntrack --ctstate RELATED,ESTABLISHED \
iptables -A HTTPD_OUT -j REJECT
# Web server scripts (CGIs) are already allowed (by a rule above) to
# send any traffic through the loopback device in order to access
# various local resources. But prohibit scripts from accessing
# anything else (such as remote machines).
iptables -A OUTPUT \
-m selinux --task-ctx system_u:system_r:httpd_sys_script_t:s0 \
# Permit all other services and users on the machine to send outbound
# traffic without restriction:
iptables -A OUTPUT -j ACCEPT
For the record, I'm not using the above solution myself: I'm using the
SECMARK-based solution that I described in my previous message:
The xt_owner netfilter module used to support iptables matching against
security contexts back in 2.6.13. I'm assuming that there is no
interest in devising the "right way" to restore this functionality long
term, since this would allow "policy" in multiple places. But if I'm
wrong, please let me know -- I'd be happy to take a shot at proposing
and writing new LSM hooks to properly support netfilter-based security
context matching that worked with all applicable LSMs.