A proof of concept implementation of RTSP over Dahua P2P protocol.

Overview

RTSP Streaming with Dahua P2P Protocol Implementation

This is a proof of concept implementation of RTSP over Dahua P2P protocol. It works with Dahua and derived cameras / NVRs.

Motivation

The Dahua P2P protocol is utilized for remote access to Dahua devices. It is commonly used by Dahua apps such as gDMSS Lite on Android or KBiVMS on Windows.

In my specific scenario, I have a KBVision CCTV system. Although I can access the cameras using the KBiVMS client, I primarily use non-Windows platforms. Therefore, I wanted to explore alternative options for streaming the video using an RTSP client, which is more widely supported. As a result, I decided to experiment with reimplementing the Dahua P2P protocol.

Files

  • Rust implementation:
    • src/*.rs - Rust source files
    • Cargo.toml - Rust dependencies
  • Python implementation:
    • main.py - Main script
    • helpers.py - Helper functions
    • requirements.txt - Python dependencies
  • Others:
    • ptcp.lua - Wireshark dissector for Dahua P2P protocol

Rust implementation

[WIP]

Python implementation

Setup

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Run
python main.py [CAMERA_SERIAL]

# Stream (e.g. with ffplay) rtsp://[username]:[password]@127.0.0.1/cam/realmonitor?channel=1&subtype=0
ffplay -rtsp_transport tcp -i "rtsp://[username]:[password]@127.0.0.1/cam/realmonitor?channel=1&subtype=0"

Usage

USERNAME and PASSWORD only need for debug mode and ffplay is required.

usage: main.py [-h] [-u USERNAME] [-p PASSWORD] [-d] serial

positional arguments:
  serial                Serial number of the camera

options:
  -h, --help            show this help message and exit
  -u USERNAME, --username USERNAME
                        Username of the camera
  -p PASSWORD, --password PASSWORD
                        Password of the camera
  -d, --debug           Enable debug mode

Limitations

  • Single threaded, so only one client can connect at a time
  • Not fully implemented (e.g. only simplex keep-alive, no mulpile connections, etc.)
  • Work better with ffplay and -rtsp_transport tcp option
  • Still unstable, can crash at any time

Protocol description

For reverse engineering the protocol, I used Wireshark and KBiVMS V2.02.0 as a client on Windows. Using ptcp.lua dissector, you can see the protocol in Wireshark easier.

For RTSP client, either VLC or ffplay can be used for easier control of the signals.

Overview

graph LR
  App[[This script]]
  Service[Easy4IPCloud]
  Device[Camera/NVR]
  App -- 1 --> Service
  Service -- 2 --> Device
  App <-. 3 .-> Device

The Dahua P2P protocol initiates with a P2P handshake. This process involves locating the device using its Serial Number (SN) via a third-party service, Easy4IPCloud:

  1. The script queries the service to retrieve the device's status and IP address.
  2. The service then communicates with the device to prepare it for connection.
  3. Finally, the script establishes a connection with the device.
graph LR
  Device[Camera/NVR]
  App[[This script]]
  Client1[RTSP Client 1]
  Client2[RTSP Client 2]
  Clientn[RTSP Client n]
  Client1 -- TCP --> App
  Client2 -- TCP --> App
  Clientn -- TCP --> App
  App <-. UDP\nPTCP protocol .-> Device

Following the P2P handshake, the script begins to listen for RTSP connections on port 554. Upon a client's connection, the script initiates a new realm within the PTCP protocol. Essentially, this script serves as a tunnel between the client and the device, facilitating communication through PTCP encapsulation.

P2P handshake

sequenceDiagram
  participant A as This script
  participant B as Easy4IPCloud
  participant C1 as P2P Server
  participant C2 as Relay Server
  participant C3 as Agent Server
  participant D as Camera/NVR

  A->>B: /probe/p2psrv
  B-->>A: ;
  A->>B: /online/p2psrv/{SN}
  B-->>A: p2psrv info

  A->>C1: /probe/device/{SN}
  C1-->>A: ;

  A->>B: /online/relay
  B-->>A: relay info

  A->>B: /device/{SN}/p2p-channel (*)

  par
    A->>C2: /relay/agent
    C2-->>A: agent info + token
    A->>C3: /relay/start/{token}
    C3-->>A: ;
  end

  B-->>A: device info

  A->>B: /device/{SN}/relay-channel + agent info

  C3-->>A: Server Nat Info!
  A->>C3: PTCP SYN
  A->>C3: PTCP request sign
  C3-->>A: PTCP sign

  A->>D: PTCP handshake (*)

Note: Both connections marked with (*) and all subsequent connections to the device must use the same UDP local port.

PTCP (a.k.a. PhonyTCP) protocol

PTCP, also known as PhonyTCP, is a proprietary protocol developed by Dahua. Its primary function is to encapsulate TCP packets within UDP packets. This is particularly useful for creating a tunnel between the client and a device that is situated behind a NAT.

Please note that there is no official documentation available for PTCP. The information provided here is based on reverse engineering.

[WIP]

You might also like...
Rustus - TUS protocol implementation in Rust.

Rustus Tus protocol implementation written in Rust. Features This implementation has several features to make usage as simple as possible. Rustus is r

RakNet Protocol implementation by Rust.

rust-raknet RakNet Protocol implementation by Rust. Raknet is a reliable udp transport protocol that is often used for communication between game clie

Rust implementation of TCP + UDP Proxy Protocol (aka. MMProxy)

mmproxy-rs A Rust implementation of MMProxy! 🚀 Rationale Many previous implementations only support PROXY Protocol for either TCP or UDP, whereas thi

A tcp over http2 + tls proxy

mtunnel A tcp over http2 + tls proxy. Usage 1. get certificates, by following steps. 2. make your config client config: { "local_addr": "127.0.0.1

Bevy asset loader that transparently supports loading over http(s)

Bevy Web Asset This is a tiny crate that that wraps the standard bevy asset loader, and adds the ability to load assets from http and https urls. Supp

A small utility to wake computers up or put them to sleep over the local network

WKSL - a wake and sleep utility An experiment in writing a small CLI utility in Rust. The program lets you wake a machine on your local network up fro

MQTT over QUIC
MQTT over QUIC

MQuicTT 🚧 This is a pre-alpha project, tread carefully 🚧 A rustlang utility/library for MQTT over QUIC. QUIC allows us to send data over multiple co

Send files over TCP. Quick and simple. Made in Rust.

SFT Multithreaded utility to send files over TCP. The sender writes a header containing the filename, and then the contents of the file, buffered, to

Streaming data over unix sockets, in Rust

Unix-socket based client/server In order to dig into Sōzu channels, I had to dig into the workings of unix sockets. What this repo contains a small so

Comments
  • Help is needed

    Help is needed

    Greeting. The project is fantastic, congratulations.

    I need help. I have an idea that I want to implement, but I can't.

    In short, I want to run a service on one server (OS) that will create a VPN to Dahua servers and enable RTSP.

    From the second computer, I want to access the IP address of the first computer and watch the stream created in this way.

    I manage connect and the system creates a VPN. However, I can't watch the stream at all.

    
    HTTP/1.1 200 Server Nat Info!
    CSeq: 5
    Content-Type:
    Content-Length: 259
    
    <body><Identify>8a 77 c6 8d b5 fe e6 58</Identify><IpEncrpt>false</IpEncrpt><LocalAddr>192.168.1.110:45660</LocalAddr><NatValueT>1</NatValueT><Policy>p2p,udprelay</Policy><PubAddr>212.200.247.162:15634</PubAddr><Relay>:0</Relay><version>6.0.0</version></body>
    ---
    DHResponse { version: "HTTP/1.1", code: 200, status: "Server", headers: {"CSeq": "5", "Content-Type": "", "Content-Length": "259"}, body: Some({"body/Relay": ":0", "body/Policy": "p2p,udprelay", "body/IpEncrpt": "false", "body/LocalAddr": "192.168.1.110:45660", "body/PubAddr": "212.200.247.162:15634", "body/version": "6.0.0", "body/Identify": "8a 77 c6 8d b5 fe e6 58", "body/NatValueT": "1"}) }
    >>> 128.14.224.146:8800
    DHPOST /device/XXXXXXXX/relay-channel HTTP/1.1
    CSeq: 8
    Authorization: WSSE profile="UsernameToken"
    X-WSSE: UsernameToken Username="P2PClient", PasswordDigest="UbOt/zqNAoDhkxOmhiK/H84YaSc=", Nonce="1390900817", Created="2023-12-16T17:52:05Z"
    
    <body><agentAddr>148.153.240.198:41617</agentAddr></body>
    ---
    <<< 148.153.240.198:41617
    HTTP/1.1 200 Server Nat Info!
    CSeq: 8
    Content-Type:
    Content-Length: 37
    
    <body><version>6.0.0</version></body>
    ---
    DHResponse { version: "HTTP/1.1", code: 200, status: "Server", headers: {"Content-Type": "", "CSeq": "8", "Content-Length": "37"}, body: Some({"body/version": "6.0.0"}) }
    >>> 148.153.240.198:41617
    PTCPPacket { sent: 0, recv: 0, pid: 0x0002ffff, lmid: 0x00000000, rmid: 0x00000000, body: Command([00 03 01 00]) }
    ---
    <<< 148.153.240.198:41617
    PTCPPacket { sent: 0, recv: 4, pid: 0x0002ffff, lmid: 0x01800b28, rmid: 0x00000000, body: Command([00 03 01 00]) }
    ---
    >>> 148.153.240.198:41617
    PTCPPacket { sent: 4, recv: 4, pid: 0x0000ffff, lmid: 0x00000001, rmid: 0x01800b28, body: Command([17 00 00 00 00 00 00 00 00 00 00 00]) }
    ---
    <<< 148.153.240.198:41617
    PTCPPacket { sent: 4, recv: 16, pid: 0x0000fff3, lmid: 0x01800b82, rmid: 0x00000001, body: Empty }
    ---
    <<< 148.153.240.198:41617
    PTCPPacket { sent: 4, recv: 16, pid: 0x0000fff3, lmid: 0x01800b82, rmid: 0x00000001, body: Command([18 00 00 00 00 00 00 00 00 00 00 00 00 4e 5f fb]) }
    ---
    Sign: 004e5ffb
    >>> 212.200.247.162:15634
    Raw [ff fe ff e7 de ed 5b bd b3 03 ef 13 41 2b 12 ae f9 ba b2 66 7f d5 ff f7 2b 61 98 57 d4 2b 81 e1 ff fb ff f7 ff fe a8 13 21 02 d2 65]
    ---
    <<< 212.200.247.162:15634
    
    
    opened by darkobg79 14
  • DevPwd_InvalidSalt

    DevPwd_InvalidSalt

    It is possible to update the protocol. On firmware 2023 this error

    python3 main.py 89B0A4EAAABBBCC

    :55246 <<< www.easy4ipcloud.com:8800 HTTP/1.1 403 Forbidden CSeq: 5 Content-Type: Content-Length: 95

    4DevPwd_InvalidSaltp2p,udprelay Error: Forbidden
    opened by p2p-sys 4
  • using P2P AS a login method

    using P2P AS a login method

    hi sir i was wondering can add a new function that will allow you to use SN to login instead of using only RTSP protocol and keep the connection alive and thank you

    opened by bii10 11
Owner
null
🤖 brwrs is a new protocol running over TCP/IP that is intended to be a suitable candidate for terminal-only servers

brwrs is a new protocol running over TCP/IP that is intended to be a suitable candidate for terminal-only servers (plain text data). That is, although it can be accessed from a browser, brwrs will not correctly interpret the browser's GET request.

daCoUSB 3 Jul 30, 2021
Bevy plugin for the GGRS P2P rollback networking library.

Bevy_GGRS Bevy plugin for the ?? GGRS P2P rollback networking library. The plugin creates a custom stage with a separate schedule, which handles corre

Georg Friedrich Schuppe 120 Jan 6, 2023
a decentralized p2p chatroom app built for practice

Yosup is an app made for the purpose of learning libp2p technology, asynchronous rust, ways to incorporate a single protocol over multiple interfaces, and cryptography.

Louis Birla 2 Jan 14, 2022
Reliable p2p network connections in Rust with NAT traversal

Reliable p2p network connections in Rust with NAT traversal. One of the most needed libraries for any server-less / decentralised projects

MaidSafe-Archive 948 Dec 20, 2022
Prototype for Koru, a parametrized p2p monetary system.Checkout

Koru About This is a prototype for Koru, a parametrized p2p monetary system consisting of: Mutual credit Voting and decision making platform (for econ

Koru 6 Oct 9, 2022
Reliable p2p network connections in Rust with NAT traversal

Reliable p2p network connections in Rust with NAT traversal. One of the most needed libraries for any server-less, decentralised project.

MaidSafe-Archive 948 Dec 20, 2022
P2P File Transfer

P2P File Transfer Overview This is a small project to help solve a problem that should've been solved by now: file transfer. For in-person file transf

Saksham Mittal 2 Dec 15, 2022
A minimalistic encryption protocol for rust async streams/packets, based on noise protocol and snow.

Snowstorm A minimalistic encryption protocol for rust async streams / packets, based on noise protocol and snow. Quickstart Snowstorm allows you to se

Black Binary 19 Nov 22, 2022
Final Project for "Computer Networking Security": A Layer-3 VPN implementation over TLS

Final Project for "Computer Networking Security": A Layer-3 VPN implementation over TLS

Siger Yang 2 Jun 7, 2022
🥧 Savoury implementation of the QUIC transport protocol and HTTP/3

quiche is an implementation of the QUIC transport protocol and HTTP/3 as specified by the IETF. It provides a low level API for processing QUIC packet

Cloudflare 7.1k Jan 8, 2023