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 filesCargo.toml
- Rust dependencies
- Python implementation:
main.py
- Main scripthelpers.py
- Helper functionsrequirements.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:
- The script queries the service to retrieve the device's status and IP address.
- The service then communicates with the device to prepare it for connection.
- 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]