SmartDNS im Eigenbau mit HAproxy und DNSmasq

Wer Online-Streaming wie z.B Netflix, Amazon-Video oder die Livestreams der verschiedenen Fernsehsender auch im Ausland nutzen will, greift oftmals auf einen der verschieden VPN-Anbieter zurück. Hier hatte ich z.B. beschrieben, wie man den Raspberry Pi als WLAN Accesspoint und VPN-Router nutzen kann.

In diesem Beitrag möchte ich eine weitere Möglichkeit aufzeigen, die wesentlich schnelle als VPN arbeitet und darüber hinaus noch recht einfach zu konfigurieren ist. Voraussetzung für die Installation sind einige Linux-Kenntnisse und ein Root-Server am gewünschten Standort. Da unser SmartDNS-Server ohne Verschlüsselung auskommt, ist er auch in Bezug auf die Speicher- und der CPU-Ausstattung nicht sehr anspruchsvoll. Ein virtueller Server mit 5-6 GB HDD, 256 MB RAM und unbegrenztem Traffic sollte hier ausreichen. Eine Liste möglicher Angebote in Deutschland findet man z.B. hier. Für 1 bis 2 € pro Monat wird hier jeder einen passenden vServer finden. Als Betriebssystem empfehle ich Ubuntu 14.04 zu nutzen. Das Projekt ist aber auch mit einer anderen Linux-Distributionen umsetzbar.

Die Installation unseres eigenen SmartDNS-Servers läuft in mehreren Schritten ab.

Schritt 1: Vorbereitende Arbeiten

Nachdem der Root-Zugang per ssh eingerichtet ist, sollte man zunächst Ubuntu aktualisieren und die notwendigen Pakete installieren:

apt-get update && apt-get upgrade
apt-get install –y git python nano dnsmasq 
apt-get install -y software-properties-common
add-apt-repository -y ppa:vbernat/haproxy-1.5
apt-get update -qq && apt-get install -y haproxy

									

Als weitere Komponente benötigen wir das in Python geschrieben Skript „dnsproxy“ von James Sigurðarson. Hier sind bereits Video-Streaming-Dienste eingearbeitet, die wir für unser Vorhaben nutzen können. Dazu laden wir es von GitHub herunter und speichern es im Verzeichnis /opt/dnsproxy/ ab.

cd /opt
git clone https://github.com/jamiees2/dnsproxy.git

									

Mit dnsproxy werden wir später die notwendigen Konfigurationsdaten generieren. Ein Setup ist in verschieden Varianten möglich. Wir werden ein „simple Setup“ (SNI) durchführen. Eine ausführliche Beschreibung der anderen Varianten findet man hier.

Schritt 2: Konfiguration config.json

Bei einem „Simple Setup“ – also der SNI-Methode, können die Standarteinstellungen übernommen werden. Dazu kopieren wir die Datei config-sample.json und benennen sie in config.json um.

{
  "iptables_location": "iptables", // Required to generate iptables rules in mode "dnat"
  "bind_ip": "*", // The IP address to bind to
  "public_ip": "", // IP address of your remote server, required for every mode
  "base_ip": "",
  // "base_ip": "x.x.x.x", // Only required for modes "dnat" and "local"
  // "base_ip": "127.0.0.51", // For local
  "base_port": 27200, // Only required for mode "dnat"
  // "local_subnet": 24, // Only required for mode "dnat"
  // "local_device": "eth1", // Only required for mode "dnat"
  "server_options": "check inter 10s fastinter 2s downinter 2s fall 1800", // Don't touch unless you know what you're doing
  "stats": {
    "enabled": true, // Set to true to enable HAProxy stats web page
    "port": 27199,
    "user": "haproxy",
    "password": "your_password"
  }
}
									

Im letzten Bereich der Konfigurationsdatei wird ein Passwort für den Zugriff auf die HAProxy-Webseite festgelegt. Damit kann man später Statistiken einsehen, die auf dem Webserver unter Port 27199 verfügbar sind. Legen Sie hier ein geeignetes Passwort fest und speichern Sie die Konfigurationsdatei im Verzeichnis /opt/dnsproxy ab.

Schritt 3: Video-Streaming Dienst auswählen und Konfigurationsdateien generieren.

Im Verzeichnis /opt/dnsproxy/proxies findet man bereits vorgefertigte Skripte für die verschiedensten Video-Streaming Anbieter der verschiedensten Länder. Im Moment sind Dateien für USA, UK, Deutschland und Polen verfügbar. Die Konfigurationsdatei für Deutschland umfasst derzeit nur den Dienst von Amazon. Sie kann aber die Grundlage für unsere eigene Konfigurationsdatei bilden. Wichtig ist es nun, den Aufbau der Datei zu verstehen. Der Provider selbst (in unseren Beispiel „amazon“) wird immer in einem Block zusammengefasst. Darunter befinden sich die verschiedenen URLs (hier als „proxies“ bezeichnet), für die wir eine Umleitung generieren müssen. Wie man an diesem Beispiel sieht, können für einen Provider mehrere Umleitungen möglich sein, die ebenfalls in Blöcken angeordnet sind.

{
  "amazon": {
    "proxies": [
      {
        "alias":"amazon_atv-ps-eu",
        "domain":"atv-ps-eu.amazon.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"amazon_atv-ext-eu",
        "domain":"atv-ext-eu.amazon.com",
        "protocols": ["http", "https"],
        "dnat": false
      },
      {
        "alias":"amazon_atv-eu",
        "domain":"atv-eu.amazon.com",
        "protocols": ["http", "https"],
        "dnat": true
      }
    ]
  }
}
									

Möchte man nun z.B. den Provider „netflix“ hinzufügen, so kann man die relevanten Daten aus der Datei poxies-us.json übernehmen. Das sieht für die Provider Amazon und Netflix nun folgendermaßen aus.

{
  "amazon": {
    "proxies": [
      {
        "alias":"amazon_atv-ps-eu",
        "domain":"atv-ps-eu.amazon.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"amazon_atv-ext-eu",
        "domain":"atv-ext-eu.amazon.com",
        "protocols": ["http", "https"],
        "dnat": false
      },
      {
        "alias":"amazon_atv-eu",
        "domain":"atv-eu.amazon.com",
        "protocols": ["http", "https"],
        "dnat": true
      }
    ]
  },
  "netflix": {
    "proxies": [
      {
        "alias":"netflix-signup",
        "domain":"signup.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-www",
        "domain":"www.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-appboot",
        "domain":"appboot.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-cbp-us",
        "domain":"cbp-us.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-akamai",
        "domain":"a248.e.akamai.net",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-api-global",
        "domain":"api-global.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-movies",
        "domain":"movies.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-movies1",
        "domain":"movies1.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-secure",
        "domain":"secure.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-moviecontrol",
        "domain":"moviecontrol.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-api",
        "domain":"api.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-api-us",
        "domain":"api-us.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-uiboot",
        "domain":"uiboot.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-cbp",
        "domain":"cbp.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-ios",
        "domain":"ios.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": false
      },
      {
        "alias":"netflix-xbox",
        "domain":"xbox.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-nrdp-31",
        "domain":"nccp-nrdp-31.cloud.netflix.net",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-nintendo",
        "domain":"nintendo.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-playstation",
        "domain":"playstation.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-nrdp",
        "domain":"nrdp.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-android",
        "domain":"android.nccp.netflix.com",
        "protocols": ["http", "https"],
        "dnat": false
      },
      {
        "alias":"netflix-playstation-net",
        "domain":"video.dl.playstation.net",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-ssm",
        "domain":"ssm.internet.sony.tv",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-ssm1",
        "domain":"ssm1.internet.sony.tv",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-ssm2",
        "domain":"ssm2.internet.sony.tv",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-ssm3",
        "domain":"ssm3.internet.sony.tv",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-treb",
        "domain":"treb.internet.sony.tv",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"netflix-wdtv",
        "domain":"www.wdtvlive.com",
        "protocols": ["http"],
        "dnat": true
      },
      {
        "alias":"netflix-htmltvui-api",
        "domain":"htmltvui-api.netflix.com",
        "protocols": ["http", "https"],
        "dnat": true
      },
      {
        "alias":"bivl-netflix-com",
        "domain":"bivl.netflix.com",
        "protocols": ["https"],
        "dnat": true
      }
    ]
  } 
}
									

Die Datei wird als proxies-de.json im Verzeichnis /opt/dnsproxy/proxies abgelegt.

Nun kommt das Python-Skript zu Anwendung, mit dem wir die notwendigen Konfigurationsdaten für die Dienste HAProxy und DNSMasq generieren. Die verschiedenen Optionen kann man mit dem Befehl ./dnsproxy.py -h einsehen:

Zuerst generieren wir die Konfigurationsdatei für HAProxy mit folgendem Befehl:

./dnsproxy.py –m sni –c de –o haproxy --ip Your_Server_IP
									

Nun die Konfigurationsdatei für DNSMasq:

./dnsprox.py –m sni –c de –o dnsmasq --ip Your_Server_IP
									

Die Option –ip spezifiziert die IP-Adresse unseres vServers, die hier natürlich einzufügen ist.

Schritt 4: Konfigurationsdateien kopieren und Dienste starten

Die mittels des Python-Skripts generierten Konfigurationsdateien sind im Verzeichnis /opt/dnsproxy/output abgelegt und müssen nun in die richtigen Verzeichnisse kopiert werden.

cd /opt/dnsproxy
cp output/haproxy.conf  /etc/haproxy/haproxy.cfg
cp output/dnsmasq-haproxy.conf  /etc/dnsmasq.conf

									

Die Dienste können danach wie folgt neu gestartet werden:

service haproxy restart
service dnsmasq restart

									

Hier sollte man auf Fehlermeldungen achten, die möglicherweise den Start des Dienstes verhindern. Ist dies der Fall, so ist bei der Erstellung der Konfigurationsdateien im Schritt 3 ein Fehler unterlaufen. Eine weitere Möglichkeit besteht darin, dass sich verschieden URLs der Videostreaming Anbieter bereits geändert haben und nicht mehr über diese Angaben erreichbar sind. Hier muss man versuchen die aktuellen Angaben herauszufinden und entsprechend einzusetzen.

Schritt 5: DNS-Konfiguration im lokalen Netzwerk anpassen

Zum Abschluss werden die DNS-Einstellungen im lokalen Netzwerk so geändert, dass zukünftig unser SmartDNS-Server alle Anfragen entgegennimmt. Es reicht auch aus, wenn man diese Änderung nur in ausgewählten Geräte (z.B. SmartTV, Apple-TV, Tablet etc.) vornimmt.

Absicherung des SmartDNS-Servers:

Grundsätzlich müsste nur der HAProxy-Dienst auf dem vServer laufen. DNSMasq könnte auch im lokalen Netzwerk, z.B. als Ubuntu-Server auf dem Raspberry Pi, eingerichtet werden. An der Vorgehensweise ändert sich in Bezug auf die Generierung der Konfigurationsdateien nichts.   Dies ist auf alle Fälle die sichere Variante.

Wählt man diese Möglichkeit nicht, so sollte zumindest der vServer mittels iptables vor Missbrauch geschützt werden. Denkbar wäre, den Zugriff nur für die eigne IP-Adressen (Home-IP) zu erlauben und alle anderen DNS-Anfragen zu sperren. Das könnte z.B. so aussehen.

# Allow all incoming connection from Home-IP
iptables -A INPUT -p tcp --dport 22 -s Home-IP -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP

iptables -A INPUT -p tcp --dport 53 -s Home-IP -j ACCEPT
iptables -A INPUT -p tcp --dport 53 -j DROP

iptables -A INPUT -p udp --dport 53 -s Home-IP -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j DROP

# Allow incoming packets from a self initiated connection to "outside"
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow HAProxy statistic and redirection on vServer
iptables -A INPUT -p tcp -m state --state NEW -d vServer-IP  --dport 27199 -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m multiport  -d vServer-IP  --dports 80,443 -j ACCEPT

									

Schlussbemerkungen:

Es ist bekannt, dass den Video-On-Demand Anbietern die “Fremdseher”, auch wenn es sich dabei um zahlende Kunden handelt, ein Dorn im Auge sind. Oftmals üben die Rechtebesitzer Druck auf diese Dienste aus. Sie wollen die Kontrolle darüber behalten, welche Inhalte wo zu sehen sind.

Aus rechtlicher Sicht ist die Umgehung eines solchen Hindernisses nicht klar geregelt, da einschlägige Urteile fehlen. Somit ist nicht abschlieflend geklärt, ob die Umgehung der GEO-Sperre rechtlich ein Problem darstellt.

In diesem Beitrag wurden ausschliefllich technische Möglichkeiten beschrieben. Rechtliche Aspekte zur Nutzung von SpartDNS-Diensten konnten nicht berücksichtigt werden und liegen in der Verantwortung der Betreiber bzw. Nutzer.

2 Gedanken zu „SmartDNS im Eigenbau mit HAproxy und DNSmasq“

  1. Hallo
    Da kommt nur folgendes wenn ich das eingebe:

    Zuerst generieren wir die Konfigurationsdatei für HAProxy mit folgendem Befehl:
    ./dnsproxy.py –m sni –c de –o haproxy –ip Your_Server_IP

    kommt:

    root@utilmanserver001:/opt/dnsproxy# ./dnsproxy.py –m sni –c de –o haproxy –ip 185.144.157.140
    usage: dnsproxy.py [-h] [-m {manual,sni,dnat,local}]
    [-o {dnsmasq,haproxy,netsh,hosts,rinetd,iptables,iproute2}]
    [-c COUNTRY [COUNTRY …]] [-d] [–ip IP]
    [–bind-ip BIND_IP] [–base-ip BASE_IP]
    [–base-port BASE_PORT] [–save] [–output-dir OUTPUT_DIR]
    [–only [ONLY [ONLY …]]] [–skip [SKIP [SKIP …]]]
    [–dnsmasq-filename DNSMASQ_FILENAME]
    [–haproxy-filename HAPROXY_FILENAME]
    [–iptables-filename IPTABLES_FILENAME]
    [–iproute2-filename IPROUTE2_FILENAME]
    [–netsh-filename NETSH_FILENAME]
    [–hosts-filename HOSTS_FILENAME]
    [–rinetd-filename RINETD_FILENAME]
    dnsproxy.py: error: unrecognized arguments: –m sni –c de –o haproxy

    Antworten

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

Diese Seite verwendet Cookies, um die Nutzerfreundlichkeit zu verbessern. Mit der weiteren Verwendung stimmst du dem zu.

Datenschutzerklärung