snom Telefone mit OpenVPN konfigurieren
Gründe für VPN
Telefone und TK-Anlage sollten zuverlässig miteinander sicher kommunizieren können.
Bei externen Telefonen wird diese Kommunikation jedoch oft durch NAT-Router und Firewalls behindert.
Auch sollten selbst betriebene TK-Anlagen für fremde Geräte nur möglichst schwer / eingeschränkt erreichbar sein.
Aus diesen Gründen kann der Zugang zur TK-Anlage über eine (UDP-basierte) VPN-Verbindung sinnvoll sein.
Die erste Konfiguration solcher externen Telefone erfolgt am einfachsten über den Redirection Service der jeweiligen Hersteller. Dessen Konfiguration bieten wir (und andere) auch als Service an.
OpenVPN
Hersteller wie snom, htek und Yealink bieten Telefone an, welche einen OpenVPN-Client in ihrer Firmware integriert haben und damit ihren Traffic direkt zu einem entfernten OpenVPN-Server verschlüsselt übertragen können. Die Konfiguration unterscheidet sich je nach Hersteller: Wir fokussieren uns hier auf die Erstellung der Konfiguration für Telefone der Firma snom. Aspekte der Sicherheit, wie bspw. Zugriffskontrolle und unterschiedliche CA, sind hier unberücksichtigt.
Server-Konfiguration
Die Konfiguration eines OpenVPN-Servers kann auf unterschiedliche Weise erfolgen.
Bei der verwendeten Konfiguration sollte insbesondere auf das verwendete Protokoll (UDP
) und den Anschluss-Typ (tun
)
sowie einer separaten key-direction
-Anweisung geachtet werden.
Das interne LAN-Netz, indem der OpenVPN-Server steht, ist in diesem Beispiel 192.168.1.0.
Sollte der OpenVPN-Server nicht gleichzeitig das Default-Gateway oder der Server sein, auf dem die TK-Anlage als B2BUA läuft, so muss zusätzlich noch ein entsprechendes Routing eingerichtet werden, damit die IP-Pakete der TK-Anlage zum Telefon finden. Möglicherweise kann hier auch der Einsatz eines Mid-Registrar-Servers sinnvoll sein.
port 1195
proto udp
dev tun
client-config-dir /etc/openvpn/clients
ca /etc/ssl/cacert.pem
cert /etc/openvpn/openvpn_certs/my.server.crt
key /etc/openvpn/openvpn_certs/my.server.key
dh /etc/openvpn/openvpn_certs/dh1024.pem
tls-auth /etc/openvpn/openvpn_certs/ta.key
key-direction 1
# Welche IPs sollen den verbundenen Clients zugewiesen werden.
server 10.30.0.0 255.255.255.0
mode server
cipher AES-256-CBC
push "cipher AES-256-CBC"
push "route 192.168.1.0 255.255.255.0"
push "route 10.30.0.0 255.255.255.0"
push "redirect-gateway def1 bypass-dhcp bypass-dns"
# Compress funktioniert nicht bei alter snom Firmware!
compress lzo
user nobody
group nobody
ifconfig-pool-persist /etc/openvpn/ipp.txt
keepalive 10 60
max-clients 25
persist-key
persist-tun
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 4
Client-Konfiguration
Die snom Telefone erwarten ihre VPN-Konfiguration in einem TAR-File. Nachfolgend wird beschrieben, wie dieses beispielhaft für ein snom D785 Telefon mit der Firmware 10.1.57.14 und einem bereits installierten VPN-Firmware-Patch automatisch erzeugt werden kann. Seine URL sollte im Web-Interface des Telefons unterhalb des aktivierten vpn-Parameters (Advanced ⇒ QoS/Security im Abschnitt Security) angegeben werden.
Das File wertet die im Server verwendeten Parameter für dev, port, proto, chipher, compress, ca sowie tls-auth (key-direction) aus und
fügt deren Werte dynamisch (bei Dateien inline) in die Konfiguration ein. Dieses erspart einen stetigen Abgleich zwischen den Konfigurationsdateien.
Benötigt wird zudem Zugriff auf die folgenden Dateien:
Datei | Erklärung |
---|---|
/etc/ssl/private/cakey.pem | CA Schlüssel zum Signieren des Telefon-Zertifikats |
/etc/ssl/cacert.pem | CA Zertifikat |
/etc/ssl/serial | Serial-Datei der CA |
/etc/openvpn/openvpn.conf | Konfigurationsdatei des OpenVPN-Servers |
#!/usr/bin/haserl-lua5.2 --shell=lua --upload-limit=256
<%
local userserial = ENV["HTTP_USER_AGENT"]:match("; snom[^ -]*.* [0-9%.]* .* (%x%x%x%x%x%x%x%x%x%x%x%x) ") or "NO-SERIAL"
local serverfile = assert(io.open("/etc/openvpn/openvpn.conf","r"),"cannot open serverconf")
local serverconf = "\n"..serverfile:read("*all"):gsub("(#[^\n]*)",""):gsub("(\n%s*\n)","\n"):gsub("\n(%s+)","").."\n"
local clientconf = "\nclient\n"..
"resolv-retry infinite\n"..
"pull\n"..
"nobind\n\n"..
"persist-key\n"..
"persist-tun\n\n"..
"dhcp-option DNS 10.30.0.1\n"..
"dhcp-option NTP 10.30.0.1\n\n"..
"explicit-exit-notify\n\n"..
"mute-replay-warnings\n"..
"remote-cert-tls server\n\n"..
"verb 0\n\n"..
"### dynamic values from server config ###\n\n"..
(serverconf:match("(port%s[^\n]*\n)") or "") ..
(serverconf:match("(proto%s[^\n]*\n)") or "") ..
(serverconf:match("(dev%s[^\n]*\n)") or "") ..
(serverconf:match("(cipher%s[^\n]*\n)") or "") ..
(serverconf:match("(compress%s[^\n]*\n)") or serverconf:match("(compress\n)") or "") ..
("remote "..ENV.HTTP_HOST:match("^([^:]*)").."\n")
local ca = serverconf:match("(<ca>.*</ca>)")
if ca then
clientconf = clientconf .. ca .."\n"
else
ca = serverconf:match("ca%s+([^%s]+)")
if ca then
file = assert(io.open(ca, "r"),"Cannot open CA-File "..ca)
clientconf = clientconf .. "<ca>\n"..file:read("*all"):match("%-%-%-%-%-BEGIN CERTIFICATE%-%-%%-%-%-.*%-%-%-%-%-END CERTIFICATE%-%-%-%-%-").."\n</ca>\n"
io.close(file)
end
end
local ta = serverconf:match("(<tls%-auth>.*</tls%-auth>)")
if ta then
clientconf = clientconf .. ta .."\n"
else
ta = serverconf:match("tls%-auth%s+([^%s]+)")
if ta then
file = assert(io.open(ta, "r"),"Cannot open TLS-AUTH-File "..ta)
clientconf = clientconf .. "<tls-auth>\n"..file:read("*all").."\n</tls-auth>\n"
io.close(file)
ta = serverconf:match("tls%-auth%s+[^%s]+%s+([01])") or serverconf:match("key%-direction%s+([01])") or "0"
clientconf = clientconf .. "key-direction "..(ta == "0" and "1" or "0").."\n"
else
clientconf = clientconf .. "## No TLS-AUTH-file specified \n"
end
end
local pkHandle = io.popen("openssl genrsa 2048 2>/dev/null")
local key = pkHandle:read("*a"):sub(1,-2)
pkHandle:close()
local crtHandle = io.popen("echo \""..key.."\" | openssl req -new -sha256 -key /dev/stdin -subj \"/C=DE/ST=Hamburg/L=Hamburg/O=voiscout/OU=pbx/CN="..userserial.."/serialNumber="..userserial..
"\" | openssl x509 -days 7600 -sha256 -CA /etc/ssl/cacert.pem -CAkey /etc/ssl/private/cakey.pem -req -CAcreateserial -CAserial /etc/ssl/serial 2>/dev/null" )
clientconf = clientconf.."<cert>\n"..crtHandle:read("*a"):sub(1,-2).."\n</cert>\n<key>\n"..key.."\n</key>"
crtHandle:close()
%>
content-type: application/x-tar
<%
local pkHandle = io.popen("mkdir -p /tmp/"..userserial .." && cd /tmp/"..userserial.."/ && echo \""..clientconf .."\" > vpn.cnf && tar cf - vpn.cnf 2>/dev/null")
io.write(pkHandle:read("*a"):sub(1,-2))
pkHandle:close()
%>