SELinux – Limit httpd Outbound Connections by Address and Port

selinux

We have a multi-host environment with httpd on one host, and an application server on a second. We'd like to use SELinux on the httpd host, and the default targeted policy causes few problems. But it does prevent httpd from making the outbound network connection to the app server host.

There's an SELinux boolean httpd_can_network_connect that if set will allow unlimited outbound connections, but I'd like to find a more narrow solution. I think I can control the destination ports by defining a new port type list:

semanage port -a -t ajp_port_t -p tcp 9010

and then create a local policy with the following:

allow httpd_t ajp_port_t:tcp_socket { name_connect };

How can I control the destination address?

Best Answer

The following SELinux policy will be needed to set this up. NOTE: I assume here that the ajp_port_t type does not actually exist on the system currently.

policy_module(myhttpd, 1.0.0)

gen_require(`
        type httpd_t;
')

type ajp_packet_t;
corenet_packet(ajp_packet_t)

type ajp_port_t;
corenet_port(ajp_port_t)

allow httpd_t ajp_port_t:tcp_socket { client_stream_socket_perms name_connect };
allow httpd_t ajp_port_t:packet { flow_in flow_out forward_in forward_out recv send };

Follow this up by the command

semanage port -a -t ajp_port_t -p tcp 9010

To manage the address, thats somewhat more complicated. And your liable to possibly cause the box to stop responding over the network! So be warned.

For this, you'll need this policy module, it permits all domains to send/recv unlabelled packets. If you dont do this first you can lose network because by default nearly all domains have no permissions to send / recv unlabelled packets!

policy_module(unconfined_packets, 1.0.0)
require {
        attribute domain;
        type unlabeled_t;
}

gen_tunable(allow_unlabeled_packets, `true');

tunable_policy(allow_unlabeled_packets, `
        allow domain unlabeled_t:packet { flow_in flow_out forward_in forward_out recv send };
')

You then must mark the packets inbound and outbound from that host using iptables.

iptables -I INPUT -p tcp --sport 9010 -s <src_addr> -j SECMARK --selctx system_u:object_r:ajp_packet_t
iptables -I OUTPUT -p tcp --dport 9010 -d <dst_addr> -j SECMARK --selctx system_u:object_r:ajp_packet_t
iptables -A INPUT -j CONNSECMARK --restore
iptables -A OUTPUT -j CONNSECMARK --save