Networking permissions have always been fairly difficult for me to
understand in SELinux.
My current understanding follows. The permissions in layers are as
follows for a client that wants to connect to a specific TCP port:
1. Domain must be able to create/open/read/write its own TCP socket,
which is accomplished like so:
allow $domain_type self:tcp_socket create_stream_socket_perms;
Now the domain can open a TCP socket but can't connect it to anything.
Also, opening a TCP socket does not mean the same thing as binding
(listening on a port as a server process).
2. Next, we have to grant it access to sending and receiving on a
network interface:
# corenet_tcp_sendrecv_generic_if
allow $domain_type $net_interface_type:netif { tcp_send tcp_recv
egress ingress };
Now the process can both open its TCP client connection and send/recv
TCP packets on the given network interface, but can't send/recv those
packets to/from any hosts (including localhost probably).
3. Next, we grant access for it to be able to send/recv to given nodes:
# corenet_tcp_sendrecv_generic_node
allow $domain_type $node_type:node { tcp_send tcp_recv sendto recvfrom };
It can now send/receive TCP packets to and from the given node, which
represents a host on the network. node_lo_t could be 127.0.0.1/32, for
instance, and you'd still need this permission to send/recv packets
from localhost.
So far it can open a client socket, read/write on that socket,
send/receive packets from a given network interface, send/receive
packets from a given network host (node), but it can't connect to or
send/receive anything due to port restrictions.
4. We now grant it access to connect and send/recv packets to a given port:
# corenet_tcp_sendrecv_generic_port
allow $domain_type $port_type:tcp_socket { send_msg recv_msg };
# corenet_tcp_connect_generic_port
allow $domain_type $port_type:tcp_socket name_connect;
Now it can fully send/receive packets to arbitrary hosts on arbitrary
ports over TCP.
-----------------------
Is my above understanding correct? In the example of a server, how do
permissions differ? Can I have a server listen to a port without being
able to be a TCP client and connect to other ports?
On 08/31/16 15:36, Naftuli Tzvi Kay via refpolicy wrote:
> Networking permissions have always been fairly difficult for me to
> understand in SELinux.
>
> My current understanding follows. The permissions in layers are as
> follows for a client that wants to connect to a specific TCP port:
>
> 1. Domain must be able to create/open/read/write its own TCP socket,
> which is accomplished like so:
>
> allow $domain_type self:tcp_socket create_stream_socket_perms;
>
> Now the domain can open a TCP socket but can't connect it to anything.
> Also, opening a TCP socket does not mean the same thing as binding
> (listening on a port as a server process).
>
> 2. Next, we have to grant it access to sending and receiving on a
> network interface:
>
> # corenet_tcp_sendrecv_generic_if
> allow $domain_type $net_interface_type:netif { tcp_send tcp_recv
> egress ingress };
>
> Now the process can both open its TCP client connection and send/recv
> TCP packets on the given network interface, but can't send/recv those
> packets to/from any hosts (including localhost probably).
>
> 3. Next, we grant access for it to be able to send/recv to given nodes:
>
> # corenet_tcp_sendrecv_generic_node
> allow $domain_type $node_type:node { tcp_send tcp_recv sendto recvfrom };
>
> It can now send/receive TCP packets to and from the given node, which
> represents a host on the network. node_lo_t could be 127.0.0.1/32, for
> instance, and you'd still need this permission to send/recv packets
> from localhost.
>
> So far it can open a client socket, read/write on that socket,
> send/receive packets from a given network interface, send/receive
> packets from a given network host (node), but it can't connect to or
> send/receive anything due to port restrictions.
>
> 4. We now grant it access to connect and send/recv packets to a given port:
>
> # corenet_tcp_sendrecv_generic_port
> allow $domain_type $port_type:tcp_socket { send_msg recv_msg };
> # corenet_tcp_connect_generic_port
> allow $domain_type $port_type:tcp_socket name_connect;
>
> Now it can fully send/receive packets to arbitrary hosts on arbitrary
> ports over TCP.
>
> -----------------------
>
> Is my above understanding correct? In the example of a server, how do
> permissions differ? Can I have a server listen to a port without being
> able to be a TCP client and connect to other ports?
Not exactly. Most of the node/netif permissions are no longer checked
as those old mechanisms have been replaced. This is a high level
summary for TCP and UDP:
1. in all cases, you need the socket access like in #1 above, plus
name_bind on the port type if you're a server and name_connect on the
port type for TCP socket connections.
2. node_bind on the node, if you're a binding
3. send/receive on packet class, only if you have SECMARK rules loaded
or network_peer_controls policycap enabled
4. If you have labeled networking configured or network_peer_controls
policycap enabled:
* node: sendto recvfrom
* netif: ingress egress
* peer: recv
Other protocols, depending on what they are, don't have as many checks.
--
Chris PeBenito