Ini merupakan bukti penerapan konsep RTSP melalui protokol P2P Dahua. Ia bekerja dengan Dahua dan kamera turunannya/NVR.
Protokol Dahua P2P digunakan untuk akses jarak jauh ke perangkat Dahua. Biasa digunakan oleh aplikasi Dahua seperti gDMSS Lite di Android atau SmartPSS, KBiVMS di Windows.
Dalam skenario spesifik saya, saya memiliki sistem CCTV KBVision. Meskipun saya dapat mengakses kamera menggunakan klien KBiVMS, saya terutama menggunakan platform non-Windows. Oleh karena itu, saya ingin mencari opsi alternatif untuk streaming video menggunakan klien RTSP, yang didukung lebih luas. Oleh karena itu, saya memutuskan untuk bereksperimen dengan mengimplementasikan kembali protokol P2P Dahua.
src/*.rs
- File sumber karatCargo.toml
- Ketergantungan karatmain.py
- Skrip utamahelpers.py
- Fungsi pembanturequirements.txt
- Ketergantungan Pythondh-p2p.lua
- Disektor Wireshark untuk protokol Dahua P2P Implementasi Rust memanfaatkan pemrograman async dan pola penyampaian pesan sehingga lebih efisien dan fleksibel.
A PoC implementation of TCP tunneling over Dahua P2P protocol.
Usage: dh-p2p [OPTIONS] <SERIAL>
Arguments:
<SERIAL> Serial number of the camera
Options:
-p, --port <[bind_address:]port:remote_port>
Bind address, port and remote port. Default: 127.0.0.1:1554:554
-h, --help
Print help
Implementasi Python pada DH-P2P adalah pendekatan yang sederhana dan mudah. Ini digunakan untuk tujuan penyusunan dan pengujian karena sifatnya yang cepat dan mudah untuk ditulis. Selain itu, penerapannya lebih linier dan mengikuti alur eksekusi top-down, sehingga lebih mudah dipahami. Python, sebagai bahasa pemrograman yang populer, semakin berkontribusi terhadap aksesibilitas dan keakrabannya di kalangan pengembang.
# 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 "
Untuk menggunakan skrip dengan perangkat yang memerlukan otentikasi saat membuat saluran, gunakan opsi -t 1
.
Saat dijalankan dalam mode --debug
atau saat --type
> 0, argumen USERNAME
dan PASSWORD
bersifat wajib. Selain itu, pastikan ffplay
berada di jalur sistem saat mode debug diaktifkan.
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
-d, --debug Enable debug mode
-t TYPE, --type TYPE Type of the camera
-u USERNAME, --username USERNAME
Username of the camera
-p PASSWORD, --password PASSWORD
Password of the camer
ffplay
dan -rtsp_transport tcp
Untuk rekayasa balik protokol, saya menggunakan Wireshark dan KBiVMS V2.02.0 sebagai klien di Windows. Dengan menggunakan disektor dh-p2p.lua
, Anda dapat melihat protokol di Wireshark dengan lebih mudah.
Untuk klien RTSP, VLC atau ffplay dapat digunakan untuk memudahkan kontrol sinyal.
grafik LR
Aplikasi[[Skrip ini]]
Layanan[Easy4IPCloud]
Perangkat[Kamera/NVR]
Aplikasi -- 1 --> Layanan
Layanan -- 2 --> Perangkat
Aplikasi <-. 3 .-> Perangkat
Protokol P2P Dahua dimulai dengan jabat tangan P2P. Proses ini melibatkan pencarian lokasi perangkat menggunakan Nomor Seri (SN) melalui layanan pihak ketiga, Easy4IPCloud:
grafik LR
Perangkat[Kamera/NVR]
Aplikasi[[Skrip ini]]
Klien1[Klien RTSP 1]
Klien2[Klien RTSP 2]
Klienn[Klien RTSP n]
Klien1 -- TCP --> Aplikasi
Klien2 -- TCP --> Aplikasi
Klienn -- TCP --> Aplikasi
Aplikasi <-. Protokol UDPnPTCP .-> Perangkat
Setelah jabat tangan P2P, skrip mulai mendengarkan koneksi RTSP pada port 554. Setelah koneksi klien, skrip memulai ranah baru dalam protokol PTCP. Pada dasarnya, skrip ini berfungsi sebagai terowongan antara klien dan perangkat, memfasilitasi komunikasi melalui enkapsulasi PTCP.
diagram urutan
peserta A sebagai skrip ini
peserta B sebagai Easy4IPCloud
peserta C1 sebagai Server P2P
peserta C2 sebagai Relay Server
peserta C3 sebagai Agent Server
peserta D sebagai Kamera/NVR
A->>B: /probe/p2psrv
B-->>J: ;
A->>B: /online/p2psrv/{SN}
B-->>A: info p2psrv
A->>C1: /probe/perangkat/{SN}
C1-->>J: ;
A->>B: /online/relay
B-->>A: info relai
A->>B: /device/{SN}/p2p-channel (*)
par
A->>C2: /relay/agent
C2-->>A: info agen + token
A->>C3: /relay/start/{token}
C3-->>J: ;
akhir
B-->>A: info perangkat
A->>B: /device/{SN}/relay-channel + info agen
C3-->>A: Info Nat Server!
A->>C3: PTCP SYN
A->>C3: tanda permintaan PTCP
C3-->>A: tanda PTCP
A->>D: jabat tangan PTCP (*)
Catatan : Kedua koneksi bertanda (*)
dan semua koneksi berikutnya ke perangkat harus menggunakan port lokal UDP yang sama.
PTCP (PhonyTCP) adalah protokol berpemilik yang dikembangkan oleh Dahua. Ini melayani tujuan merangkum paket TCP dalam paket UDP, memungkinkan pembuatan terowongan antara klien dan perangkat di belakang NAT.
Harap dicatat bahwa dokumentasi resmi untuk PTCP tidak tersedia. Informasi yang diberikan di sini didasarkan pada rekayasa balik.
Header paket PTCP adalah struktur tetap 24-byte, seperti diuraikan di bawah ini:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| magic |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sent |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| recv |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| pid |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| lmid |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rmid |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
magic
: Nilai konstan, PTCP
.sent
dan recv
: Lacak masing-masing jumlah byte yang dikirim dan diterima.pid
: ID Paket.lmid
: ID Lokal.rmid
: ID Lokal dari paket yang diterima sebelumnya.Ukuran badan paket bervariasi (0, 4, 12 byte atau lebih) berdasarkan jenis paket. Strukturnya adalah sebagai berikut:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| type | len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| realm |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
type
: Menentukan jenis paket.len
: Panjang bidang data
.realm
: ID Realm koneksi.padding
: Padding byte, selalu disetel ke 0.data
: Data paket.Jenis paket:
0x00
: SYN, isi selalu 4 byte 0x00030100
.0x10
: Data TCP, dimana len
adalah panjang data TCP.0x11
: Permintaan port yang mengikat.0x12
: Status koneksi, dengan data berupa CONN
atau DISC
.realm
disetel ke 0):0x13
: Detak jantung, dimana len
selalu 0.0x17
0x18
0x19
: Otentikasi.0x1a
: Respons server setelah 0x19
.0x1b
: Respons klien setelah 0x1a
. Proyek ini terinspirasi dan dipengaruhi oleh proyek dan orang-orang berikut: