Posted at

複数のMiniDLNAインスタンスを起動して、アクセス制御する

More than 3 years have passed since last update.


動機

MiniDLNAには認証や認可の機能がなく、パートナーや家族に見られたくない あんなファイルやこんなファイルを隠す術がありません。そこで、


  • 1つのホスト上で複数のMiniDLNAインスタンスを立ち上げて、

  • それぞれのインスタンスで公開するディレクトリを変え、

  • それぞれのインスタンスにアクセスできるIPアドレスやMACアドレスを制限することにより、

擬似的にアクセス制御を掛けてみることにしました。

これによって、


  • このディレクトリはLAN内の全てのDLNAクライアント機器から見えるが、

  • あのディレクトリは自分のスマホからしか見えない

というようなことが実現できます。


Dockerfileを記述する

準備が楽なので Docker上でMiniDLNAを動かします。まずはそのためのDockerfileを記述します。


Dockerfile

FROM ubuntu:16.04

MAINTAINER flny flny@example.com

RUN apt-get update && apt-get install -y \
minidlna

ADD start.sh /start.sh
RUN chmod +x /start.sh

EXPOSE 8200
EXPOSE 8201
EXPOSE 1900/udp

CMD /start.sh



start.sh

#!/bin/bash

service minidlna restart
/bin/bash


Ubuntu 16.04では ppaやbackportsなしでMiniDLNAをインストールできます。そのバージョンも1.1.5と新しくなり重大なバグが修正されているので ベースイメージは16.04としました。

また、立ち上げるインスタンスの数だけTCPのポートをEXPOSEに記述します。上記例では8200と8201の2つです。これらとは別に1900/udpも開ける必要があります。


MiniDLNAの設定ファイルを記述する

MiniDLNAの設定ファイル(デフォルトのファイル名はminidlna.conf)をインスタンスの数だけ記述します。


minidlna.default.conf

()

media_dir=V,/mnt/pub/movie
()
# Port number for HTTP traffic (descriptions, SOAP, media transfer).
# This option is mandatory (or it must be specified on the command-line using
# "-p").
port=8200
()
# Name that the DLNA server presents to clients.
# Defaults to "hostname: username".
friendly_name=default
()
# Serial number the server reports to clients.
# Defaults to 00000000.
serial=681019830597110
uuid=0fc28baa-b6df-4002-9a7f-5994c4b85fc0
()


minidlna.rated.conf

()

media_dir=V,/mnt/pub/rated
()
# Port number for HTTP traffic (descriptions, SOAP, media transfer).
# This option is mandatory (or it must be specified on the command-line using
# "-p").
port=8201
()
# Name that the DLNA server presents to clients.
# Defaults to "hostname: username".
friendly_name=rated
()
# Serial number the server reports to clients.
# Defaults to 00000000.
serial=681019830597110
uuid=5a9884be-267d-4164-86c0-d638d98bf09b
()

色々な設定が含まれていますが、少なくとも下記のパラメータをインスタンスごとに変更します。



  • media_dir公開するディレクトリ


  • portポート番号(DockerfileのEXPOSEに書いたポート)


  • friendly_nameクライアントから見たサーバの名称


  • uuid任意のuuid

uuidを記述するところがこの記事唯一のポイントです。uuidの記述がないと、インスタンスを複数立ち上げてもクライアントには1つしか認識されません。uuidgenコマンドやOnline UUID Generatorで uuidを生成できます。


docker-compose.yml を記述する

インスタンスの数だけコンテナの定義を記述します。イメージはDockerfileで定義した共通のものを使用しますが、MiniDLNAの設定ファイルはコンテナごとに変えます(volumes:の部分)。


docker-compose.yml

minidlna:

image: minidlna
container_name: dlna.default
tty: true
net: "host"
volumes:
- ./docker/minidlna/minidlna.default.conf:/etc/minidlna.conf
command:
"/start.sh"

rated:
image: minidlna
container_name: dlna.rated
tty: true
net: "host"
volumes:
- ./docker/minidlna/minidlna.rated.conf:/etc/minidlna.conf
command:
"/start.sh"



コンテナを作成してMiniDLNAインスタンスを起動する

docker build で イメージ"minidlna"を作成し、docker-compose upでコンテナを作成します。

$ docker build -t minidlna <Dockerfileのあるディレクトリ>

$ docker-compose up -d minidlna rated

DLNAクライアントを起動して、DLNAサーバが2つ見えたら成功です。


ファイアウォールでアクセス制御する

あとは、特定のDLNAクライアントのIPアドレスやMACアドレスをファイアウォールで弾けばOKです。IPアドレスならufwが簡単でよいですが、MACアドレスだとiptablesを直接使う必要があります。以下はufwの例です。

192.168.0.101 がホストのIPアドレス、192.168.0.201がスマホのIPアドレスだとして、rated(ポート8201)はスマホからしか見えないようにファイアウォールを設定します。

# デフォルトを許可にする

$ sudo ufw default ALLOW
Default incoming policy changed to 'allow'
(be sure to update your rules accordingly)

# ファイアウォールを有効化する
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

# スマホから rated(ポート8201)への接続を許可する
$ sudo ufw allow from 192.168.0.201 to 192.168.0.101 port 8201
Rule added

# スマホ以外から rated(ポート8201)への接続を拒否する
$ sudo ufw deny from any to 192.168.0.101 port 8201
Rule added

これでスマホ以外のクライアントからはratedが見えなくなりました。

以上