Thursday, March 31, 2011

Setup your own DLNA server

DLNA is a standards-based technology whose main goal is to ease the sharing of multimedia contents. DLNA is an open protocol based on UPnP.

This article describes how to install and configure a DLNA server. This software is going to be installed on a home server. Just as a comment, this home server is a very low power consumption machine (Atom N550 board) running a very powerful OS: 64 bit CentOS 5.5.

We started with a brief comparison and testing of some of the most popular DLNA servers for Linux uShare, MediaTomb and MiniDLNA). That was not an exhaustive comparison, but just a few quick tests. After that quick preview, we finally decided to use MiniDLNA.

The authors of the MiniDLNA project offer a statically compiled version, which makes very easy to install the software. Download it, and optionally, you can make some changes to file permissions in order to keep them consistent with the rest of your system.

Let's assume that you downloaded the installation package on /tmp

Previously to the installation, we set root as the owner of the files (optional) just to avoid having an unreferenced owner, then, we unpack the software.


# mkdir /tmp/mini
# tar -xzf /tmp/minidlna_1.0.19_static.tar.gz -C /tmp/mini
# chown -R root:root /tmp/mini
# cp -r /tmp/mini/* /


The configuration is really simple. You have a self-explaining configuration file (/etc/minidlna.conf) with a few options. Just indicate which interface are you running the service on, and the directory containing the media to share. In my case, these were the only changes I made, keeping the rest of the options with the default values.


network_interface=eth0
media_dir=/usr/local/media/
friendly_name=Multimedia


The most difficult task is to configure the firewall (iptables, since it is a CentOS based server) properly. This home server offers public services to the outside. External services are separated from internal ones, being offered through a different interface. Even so, disabling the firewall is not an option.

First of all, we launch the service just to examine the ports that must be kept open:


# /usr/sbin/minidlna
# lsof -i4 -n | grep minidlna
minidlna 12964 root 8u IPv4 1155301 UDP *:ssdp
minidlna 12964 root 9u IPv4 1155302 TCP *:trivnet1 (LISTEN)
minidlna 12964 root 10u IPv4 1155303 UDP 192.168.1.8:37167
minidlna 12965 root 8u IPv4 1155301 UDP *:ssdp
minidlna 12965 root 9u IPv4 1155302 TCP *:trivnet1 (LISTEN)
minidlna 12965 root 10u IPv4 1155303 UDP 192.168.1.8:37167
minidlna 12968 root 8u IPv4 1155301 UDP *:ssdp
minidlna 12968 root 9u IPv4 1155302 TCP *:trivnet1 (LISTEN)
minidlna 12968 root 10u IPv4 1155303 UDP 192.168.1.8:37167


Ports ssdp (1900/udp) and trivnet1 (8200/tcp) are proper of this service. The other port (37167/udp) varies in every execution.

I recognize not being an expert setting firewall rules, but firewall configuration in CentOS in this case resulted to be a very frustrating task.

After almost two whole days spent reading threads, tutorials and comments about UPnP, SSDP, DLNA, multicast, routing and filtering, I finally obtained a firewall configuration that, so far, seems to work properly. Neither more permissive than necessary nor too much complicated.

Maybe due to my limited knowledge about iptables, I was not able to introduce these rules from the command line to behave as I expected, so, I had to edit, finally, the /etc/sysconfig/iptables file in order to introduce these rules. I added two rules in the RH-Firewall-1-INPUT section, just before the REJECT rule.


...
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -d 192.168.1.8 -p tcp -m tcp --dport 8200 -j ACCEPT
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -d 239.255.255.250 -p udp -m udp --dport 1900 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT


The IP 192.168.1.8 is where the machine offers services to other devices in the LAN (192.168.1.0/24)

First rule allow computers on the LAN to access the server on the port 8200/tcp
Second rule allow computers on the LAN (including the same server) to access the SSDP service (1900/udp) on a fixed multicast address (239.255.255.250)

Restart iptables after these changes, and you will have a working DLNA server without compromising the security of your server.

6 comments:

TheRabidGranny said...

Cool - this will come in handy when I harden my Arch Linux box.

Edu Melo said...

I installed this server recently here. If I had found this before it'd spend a lot less time.
But something I hadn't done: I didn't open the 1900 port at iptables and apparently it's working fine.
Do you know what I'll get if I open this port?

Kevin J Walters said...

The minidlna process appears to run as root in your example. The process does not need that privilege so it would be more secure to run it as a different user, perhaps a dedicated user for that process, maybe with a special group used to permission non-publically readable files for serving.

The only issue for non root use i've noted so far is the one discussed here about max_user_watches.

http://sourceforge.net/projects/minidlna/forums/forum/879957/topic/4377709

Sumit Arora said...

Over OPENVPN - Forwarding of UPnP SSDP Multicast Packets from One Network to Another

Network Configuration :

(PC-A-Network-A - 192.168.60.X) --Switch(Router) -- Internet (ISP) -- Switch (Router) -- (PC-B-Network-B - 192.168.10.X)

What is happening ?

libupnp device is running at PC-A-Network-A(192.168.60.128) and sending multicast packets(SSDP-Notify) at 239.255.255.250:1900

libupnp ctrlpoint is running at PC-B Network-B(192.168.10.104) and sending multicast packets(SSDP-Msearch) at 239.255.255.250:1900

OpenVPN Server is running at PC-B Network-B

OpenVPN Client is running at PC-A Network-A

(open VPN fully configured, as both network can ping each other)

Via using smcroute ( from this : http://bda.ath.cx/blog/2009/01/24/multicast-routing-upnp-traffic-with-linux/), its possible
to route PC-A-Network Packets to Network-B (SSDP-Multicast Packets), and vice versa.

What is not hapening ?

PC-A sending multicast SSDP Packets , and those are forwarded via openVPN to Network -B and vice versa, but no one accepts the multicast packets received from another network ?

Is there any body can explain ?

Do I need to configure iptables rules so that packet should be forwarded ? Or required to add some NAT rules or Is it possible to do this scenario ?

Sumit Arora said...

Over OPENVPN - Forwarding of UPnP SSDP Multicast Packets from One Network to Another

Network Configuration :

(PC-A-Network-A - 192.168.60.X) --Switch(Router) -- Internet (ISP) -- Switch (Router) -- (PC-B-Network-B - 192.168.10.X)

What is happening ?

libupnp device is running at PC-A-Network-A(192.168.60.128) and sending multicast packets(SSDP-Notify) at 239.255.255.250:1900

libupnp ctrlpoint is running at PC-B Network-B(192.168.10.104) and sending multicast packets(SSDP-Msearch) at 239.255.255.250:1900

OpenVPN Server is running at PC-B Network-B

OpenVPN Client is running at PC-A Network-A

(open VPN fully configured, as both network can ping each other)

Via using smcroute ( from this : http://bda.ath.cx/blog/2009/01/24/multicast-routing-upnp-traffic-with-linux/), its possible
to route PC-A-Network Packets to Network-B (SSDP-Multicast Packets), and vice versa.

What is not hapening ?

PC-A sending multicast SSDP Packets , and those are forwarded via openVPN to Network -B and vice versa, but no one accepts the multicast packets received from another network ?

Is there any body can explain ?

Do I need to configure iptables rules so that packet should be forwarded ? Or required to add some NAT rules or Is it possible to do this scenario ?

Anonymous said...

My DLNA dont work. In minidlna.log have error
minissdp.c:316: error: sendto(udp_notify=9, 192.168.1.103): Invalid argument .I think maybe the problem is in my rooter /linksys work in AP mode/