troglobit / pimd

PIM-SM/SSM multicast routing for UNIX and Linux
http://troglobit.com/projects/pimd/
BSD 3-Clause "New" or "Revised" License
202 stars 90 forks source link

Problems creating multicast routes with SELinux enforcing mode #109

Open ghost opened 7 years ago

ghost commented 7 years ago

Hello,

I am seeing issues with mrouted creating the multicast routing cache when SELinux is in enforcing mode. I am sending a multicast video stream from a machine using VLC and forwarding the stream to another system that is also running mrouted. A fourth machine requests the stream using VLC. This setup works with SELinux in permissive mode on both machines that are running mrouted. Both mrouted configs have all rules commented out.

Machine A (sending multicast stream) <---> Machine B (mrouted in enforcing) <---> Machine C (mrouted in permissive) <---> Machine D (requesting video stream)

I am running mrouted version 3.9.6 (I have also tried 3.9.8) on RHEL 6. I have verified the same behavior occurs in RHEL 5 and 7. I am also seeing this with pimd (master branch, commit dc27fea).

The system seeing issues (Machine B in the diagram above) is using SECMARK to label packets in the mangle table of IPTables. When packets come into the system running mrouted, the following flow is observed using TRACE debugging of IPTables:

Jul 26 21:29:59 localhost kernel: TRACE: mangle:PREROUTING:rule:1 IN=eth0 OUT= MAC=<redacted> SRC=192.168.177.200 DST=239.1.1.101 LEN=1356 TOS=0x00 PREC=0x00 TTL=20 ID=23017 DF PROTO=UDP SPT=39773 DPT=5191 LEN=1336
Jul 26 21:29:59 localhost kernel: TRACE: mangle:Label_Multicast:rule:1 IN=eth0 OUT= MAC=<redacted> SRC=192.168.177.200 DST=239.1.1.101 LEN=1356 TOS=0x00 PREC=0x00 TTL=20 ID=23017 DF PROTO=UDP SPT=39773 DPT=5191 LEN=1336
Jul 26 21:29:59 localhost kernel: TRACE: mangle:Label_Multicast:return:2 IN=eth0 OUT= MAC=<redacted> SRC=192.168.177.200 DST=239.1.1.101 LEN=1356 TOS=0x00 PREC=0x00 TTL=20 ID=23017 DF PROTO=UDP SPT=39773 DPT=5191 LEN=1336
Jul 26 21:29:59 localhost kernel: TRACE: nat:PREROUTING:rule:1 IN=eth0 OUT= MAC=<redacted> SRC=192.168.177.200 DST=239.1.1.101 LEN=1356 TOS=0x00 PREC=0x00 TTL=20 ID=23017 DF PROTO=UDP SPT=39773 DPT=5191 LEN=1336
Jul 26 21:29:59 localhost kernel: TRACE: nat:PREROUTING:policy:2 IN=eth0 OUT= MAC=<redacted> SRC=192.168.177.200 DST=239.1.1.101 LEN=1356 TOS=0x00 PREC=0x00 TTL=20 ID=23017 DF PROTO=UDP SPT=39773 DPT=5191 LEN=1336
Jul 26 21:29:59 localhost kernel: mroute: pending queue full, dropping entries.
Jul 26 21:29:59 localhost kernel: type=AVC msg=audit(1501104611.910:4867): avc:  denied  { recv } for  saddr=192.168.177.200 daddr=239.1.1.101 scontext=system_u:system_r:foo_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=packet

To summarize:

raw (PREROUTING) -> mangle (PREROUTING) -> proper SELinux label applied -> nat (PREROUTING) (see https://www.frozentux.net/iptables-tutorial/chunkyhtml/images/tables_traverse.jpg)

After the nat table, the packets are dropped. The routing decision to go to the mangle (FORWARD) never occurs because the packet is given the SELinux domain of unlabeled_t.

This is the mangle table in IPTables that I am using:

:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:Label_Multicast - [0:0]

-A Label_Multicast -j SECMARK --selctx system_u:object_r:foo_t:s0
-A Label_Multicast -j ACCEPT

-A INPUT -p udp --destination 224.0.0.0/4 -j Label_Multicast
-A OUTPUT -p udp --destination 224.0.0.0/4 -j Label_Multicast
-A INPUT -p igmp -j Label_Multicast
-A OUTPUT -p igmp -j Label_Multicast

COMMIT

When running the system in SELinux permissive mode, I see the same denials. Once I let the actual multicast stream to flow through my system, I see that ip mroute shows the multicast routing cache was established. I then do not see any unlabeled packets.

The possible relation to the multicast routing cache is also seen when I use smcroute and specify static routes in my config. I boot in enforcing with smcroute, send my multicast stream through the system, and I do not see any unlabeled packets and multicast routing cache for my data flow exists.

To me it seems that IPTables needs the multicast routing cache to exist before it knows how to make a routing decision, as the smcroute test shows. It's also weird that IPTables does allow the packet to be labeled with the context in the Label_Multicast chain, but then the packet still has the unlabeled_t label after the nat table and no routing decision can be made.

Do you have any ideas what could be behind this issue? Should I reach out to the netfilter list instead?

Thanks!

ghost commented 7 years ago

I just realized I posted this to the wrong project. Please feel free to close and I'll open on the mrouted github page if necessary.

troglobit commented 7 years ago

Multicast routing and netfilter is a special kind of hell ... have you tried flushing connection tracking?

ghost commented 7 years ago

I did flush connection tracking with conntrack -F and it did not make a difference. I have been reading around more today and it appears there is no connection tracking for multicast in IPTables. There is also no IPTables helper for multicast connection tracking.

It very well might be related to connection tracking.

troglobit commented 7 years ago

Unfortunately I have no other ideas, never used SELinux myself. I know we had issues at work though when doing 1-to-1 NAT (netmap) of multicast, turned out to be due to conntrack locking on to the multicast before the NAT, so for each new multicast rule being set in the kernel we had to do a conntrack flush. I later added a -e CMD to SMCRoute so it could call conntrack -F for each (*,G) route it added.

Well, let's leave this issue open, maybe someone else has a similar issue and can chime in.