Fedora firewall with UPnP?

5,149

Solution 1

First thing you need to know is how UPnP IGD protocol is working. You choose random local UDP port and from it you send discovery request to well-known multicast address 239.255.255.250 and UDP port 1900. UPnP IGD server (running on your router) listen for those multicast queries and send you back unicast UDP reply from randomly chosen port to your ip address and port from which discovery request was sent. But such reply is not paired by conntrack iptables module to your sent request so, received reply is dropped by iptables. This is why enabling all UDP ports or disabling firewall helped. In that UDP reply is location of your UPnP IGD server and client then establish classic TCP connection with UPnP IGD server. So the only problem is how to write a rule for receiving UDP reply to that multicast discovery request.

Via ipset it is possible. I described it in answer at https://serverfault.com/a/911286:

$ ipset create upnp hash:ip,port timeout 3
$ iptables -A OUTPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j SET --add-set upnp src,src --exist
$ iptables -A INPUT -p udp -m set --match-set upnp dst,dst -j ACCEPT

In IPv6 are UPnP packets sent to multicast address ff02::c or ff05::c. So rules would look like:

$ ipset create upnp6 hash:ip,port timeout 3 family inet6
$ ip6tables -A OUTPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist
$ ip6tables -A OUTPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist
$ ip6tables -A INPUT -p udp -m set --match-set upnp6 dst,dst -j ACCEPT

Some UPnP servers (but not all) periodically (e.g. every 30s) announce theirself via multicast UDP packet to well-known address/port. If you have such server and also client which is listening for these multicast packets, then iptables rule very is simple:

$ iptables -A INPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT

And equivalent for IPv6:

$ ip6tables -A INPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j ACCEPT
$ ip6tables -A INPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j ACCEPT

In your question you described something similar to above iptables rule, but you have did one big mistake: You specified source port, instead of destination: --sport 1900. UPnP UDP packets are sent from random source ports to fixed destination port 1900.

You also described that upnp-inspector can detect your UPnP IGD router after you added port 1900 to trusted (probably both source and destination), but it was slower as disabling firewall. This perfectly matches above description of periodic announcement as upnp-inspector was waiting when your router send next announce packet.

Solution 2

I found a slightly secure method than disable the firewall, which is allow port range from 10000 to 59999. And you don't need to open 1900.

Share:
5,149
Cheng
Author by

Cheng

Updated on September 18, 2022

Comments

  • Cheng
    Cheng almost 2 years

    I'm using Fedora 15 and Transmission BT client. Transmission can't open ports unless the firewall is disabled.

    I searched some posts that said add 1900 to the trusted ports, or via a iptable rule: -A INPUT -m state --state NEW -m udp -p udp --sport 1900 -j ACCEPT". However, Transmission can't open ports anyway.

    I also tested with upnp-inspector, which is better than Transmission, it could detect my upnp router after add 1900 to the trusted ports, but the detection is slower than if the firewall is disabled.

    Any ideas on how to let Transmission UPnP works with the Firewall?

  • J. M. Becker
    J. M. Becker over 12 years
    Yes, Its just slightly better... The main issue is even if you open ports on the router, Iptables will block that port at your localhost. I have strong Iptables rules, then port forwards for my specific apps. Then I disable UPNP, and then I get the benefit of the firewall.
  • user2948306
    user2948306 almost 5 years
    Somewhat controversially, Fedora Workstation 21 and above default to allowing all ports from 1025 to 65535 :-). I also note, if your router supports NAT-PMP as an alternative to uPnP, that doesn't require you to have a port open in firewalld for the NAT-PMP connection. You only have to open the Transmission port in firewalld, as normal (port 51413, by default)