0

I have installed two Dahua IPC-C15 IP cameras in an internal network and want to make them accessible via VPN.

The local network is set up as follows:

  • default GW: 192.168.1.1
  • vpn-connected machine: 192.168.1.31
  • IP camera: 192.168.1.4{0,1}
  • dynamic subnet (other machines): 192.168.1.50-90

I keep the default GW and vpn-connected machine separate and would like to avoid mixing them (default GW is a stock ADSL router, vpn client is a bit flaky from a hardware point of view ).

I have considered the following plan for exposing the cameras via VPN:

  1. Allocating unique ports for all services on the cameras
  2. Forwarding the specific ports on the VPN-connected machine
  3. Accessing the services via VPN on the VPN-connected machine

The diagram below should make it clearn

[cam-0]
(1080, 5664)    \
                  --> [vpn-client]             --> (VPN)
[cam-1]              (forwards 1080, 1081)
(1081, 5665)    /    (         5664, 5665)

The cameras work just fine with the altered ports, so I tried to make them available via port forwarding. I forwarded all the needed ports for cam-0 (was a bit overzealous even)

iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 1080 -j DNAT --to-destination 192.168.1.40:1080
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 1554 -j DNAT --to-destination 192.168.1.40:1554
iptables -t nat -A PREROUTING -p udp -i eth0 --dport 1554 -j DNAT --to-destination 192.168.1.40:1554
iptables -t nat -A PREROUTING -p udp -i eth0 --dport 37777 -j DNAT --to-destination 192.168.1.40:37777
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 37777 -j DNAT --to-destination 192.168.1.40:37777
iptables -t nat -A PREROUTING -p udp -i eth0 --dport 37778 -j DNAT --to-destination 192.168.1.40:37778
iptables -A FORWARD -p udp -d 192.168.1.40 --dport 37778 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -p tcp -d 192.168.1.40 --dport 37777 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -p tcp -d 192.168.1.40 --dport 1080 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -p tcp -d 192.168.1.40 --dport 1554 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -t nat -A POSTROUTING -j MASQUERADE

The end result is that HTTP access works just fine, but RTSP playback does not. I have not dared to try ONVIF discovery, it's probably a mess.

The RTSP errors with ffplay are the ones below

$ ffplay -hide_banner 'rtsp://$USER:$PASS@192.168.1.31:1554'
[rtsp @ 0x7fa124000b80] UDP timeout, retrying with TCP   0B f=0/0   
[rtsp @ 0x7fa124000b80] method PAUSE failed: 455 Method Not Valid in This State
[rtsp @ 0x7fa124000b80] Could not find codec parameters for stream 0 (Video: h264, none): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
Input #0, rtsp, from 'rtsp://admin:50076929dhA!@192.168.1.31:1554':
  Metadata:
    title           : Media Server
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: h264, none, 90k tbr, 90k tbn, 180k tbc
    Stream #0:1: Audio: aac, 16000 Hz, mono, fltp
[rtsp @ 0x7fa124000b80] UDP timeout, retrying with TCP   0B f=0/0   
[rtsp @ 0x7fa124000b80] method PAUSE failed: 455 Method Not Valid in This State

If I look at the iptables stats on the machine doing the forwarding, packets seem to flow:

# iptables -L -vn

Chain INPUT (policy ACCEPT 9827 packets, 6479K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 196 packets, 17202 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1620  183K ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.1.40         tcp dpt:1080 state NEW,RELATED,ESTABLISHED
  107 21217 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.1.40         tcp dpt:1554 state NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            192.168.1.40         udp dpt:1554 state NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            192.168.1.40         udp dpt:37778 state NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.1.40         tcp dpt:37777 state NEW,RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT 857 packets, 96412 bytes)
 pkts bytes target     prot opt in     out     source               destination

# iptables -t nat -L -vn
Chain PREROUTING (policy ACCEPT 233 packets, 45610 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  128  7680 DNAT       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:1080 to:192.168.1.40:1080
    7   420 DNAT       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:1554 to:192.168.1.40:1554
    0     0 DNAT       udp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            udp dpt:1554 to:192.168.1.40:1554
    0     0 DNAT       udp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            udp dpt:37777 to:192.168.1.40:37777
    0     0 DNAT       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:37777 to:192.168.1.40:37777
    0     0 DNAT       udp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            udp dpt:37778 to:192.168.1.40:37778

Chain INPUT (policy ACCEPT 233 packets, 45610 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 246 packets, 23141 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  455 38579 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0

I'm out of ideas at the moment, so any suggestions on how to move this forward are very much appreciated.

Robert Munteanu
  • 1,542
  • 5
  • 22
  • 38

1 Answers1

0

Apparently the forwarding rules work, I just had to ask ffmpeg to use tcp using ffplay -rtsp_transport tcp.

Furthermore, the Android app I'm using (Ovnifer) is happy with just the HTTP and RSTP ports forwarded so I'm calling this done.

Robert Munteanu
  • 1,542
  • 5
  • 22
  • 38
  • 1
    Look into using a VPN instead, rstp auth is insecure plaintext, unless you want others to find it – Jacob Evans Jun 26 '18 at 04:20
  • @JacobEvans - that's a good point. I was unsure, but I am treating all of RTSP as plain-text. That's why all access outside the original LAN goes via VPN ( the vpn-client → VPN part of my diagran ). – Robert Munteanu Jun 26 '18 at 10:31
  • 1
    There's a RTSP iptables helper which isn't in mainline kernel which works with conntrack and with NAT on a router without having to put the (UDP) data port in a rule ( https://packages.debian.org/stretch/nat-rtsp-dkms from upstream https://github.com/maru-sama/rtsp-linux ). Works fine here from kernels 4.9.x to 4.17.x (and for way older kernels too). I'm using it behind MASQUERADE/SNAT, but I believe it works also in the "opposite" way too (DNAT). – A.B Jun 26 '18 at 19:53
  • Thanks for the info @A.B . I have a stable setup now, but if I run into any troubles I'll take a look at the links you provided. – Robert Munteanu Jul 06 '18 at 12:43