TSDuck-ի օգտագործումը IP(TS)-կայքերի մոնիտորինգի համար

Այսօր արդեն գոյություն ունեն պատրաստի (պրոպրիետար) լուծումներ IP(TS) հոսքերի մոնիթորինգի համար, օրինակ, VB և iQ։ Դրանք ունեն բավականին հարուստ ֆունկցիոնալություն, և նման լուծումները սովորաբար առաջարկում են մեծ օպերատորները, որոնք աշխատում են հեռուստա ծառայությունների վրա։ Այս հոդվածում նկարագրվում է բաց աղբյուրի նախագծի վրա հիմնված լուծում, TSDuck։ Այն նախատեսված է IP(TS) հոսքերի նվազագույն վերահսկողության համար՝ CC (continuity counter) հաշվիչով և բիթռեյթով վերահսկելու համար։ Օգտագործման հնարավոր տարբերակը՝ փ paketներ կամ ամբողջ հոսքը վերահսկել վարձակալված L2 ալիքով (որն ակնհայտորեն հնարավոր չէ պատշաճ մոնիթորինգ անել, օրինակ, կորստի հաշվիչներն ընթերցելով ճանապարհներին):

Շատ կարճ տեղեկատվություն TSDuck-ի մասին

TSDuck-ը բաց կոդով (2-Clause BSD լիցենզիայով) ծրագիր է (կոնսոլային օգտակար ծրագրերի հավաքածու և սեփական օգտակար ծրագրերի կամ պլագինների մշակման գրադարան) TS հոսքերի հետ աշխատելու համար։ Այն կարող է ընդունել IP (multicast/unicast), http, hls, dvb-թալարներ, dektec dvb-asi դեմոդուլատորը, ունի ներքին TS հոսքի գեներատոր և հանված ֆայլերից ընթերցման հնարավորություն։ Արտահոսքը կարող է լինել գրություն ֆայլում, IP (multicast/unicast), hls, dektec dvb-asi և HiDes մոդուլատորներ, խաղացողներ (mplayer, vlc, xine) և drop: Ներդրման և արտահոսի միջև կարելի է ներդնել տարբեր երթի վերամատուցողներ, օրինակ, PID-ների վերամուտ, սքրեմբլավորում/դեսքրեմբլավորում, CC հաշվիչների վերլուծություն, բիթռեյթի հաշվարկի համարը և մյուս ավանդական TS հոսքերի գործողությունները։

Այս հոդվածում որպես մուտք օգտագործվելու են IP հոսքեր (multicast), օգտագործվում են bitrate_monitor (անգամ անունից պարզ է, թե ինչ է) և continuity (CC հաշվիչների վերլուծություն) պրոցեսորները։ Ինտեգրված խնդիրների մեծամասնությունը կարելի է հեշտությամբ փոխարինել IP multicast-ով այլ մուտքային տեսակով, որը TSDuck-ը աջակցում է։

Կա հիմնական պաշտոնական հավաքածուներ/փաթեթներ TSDuck-ի համար հիմնական գործող համակարգերի համար։ Debian-ի համար չկա, բայց առանց խնդիրների հաջողվեց հավաքել debian 8 և debian 10-ի համար։

Հետագայում օգտագործվում է TSDuck 3.19-1520 տարբերակը, որպես OS օգտագործվում է Linux (լուծման պատրաստման համար օգտագործվել է debian 10, իսկ իրական օգտագործման համար՝ CentOS 7)

TSDuck և OS պատրաստում

Նախքան իրական հոսքերի մոնիտորինգը, պետք է համոզվեք, որ TSDuck-ը կոռեկտ գործում է և ցանցային քարտի կամ OS-ի (սոկետի) մակարդակում չկա բաժանումներ: Սա անհրաժեշտ է, որպեսզի այնուհետև չսպասեք, թե որտեղ են կատարվել բաժանումները՝ ցանցում թե «ծանրաբեռնված» սերվերում: Ցանցային քարտի մակարդակում բաժանումները ստուգելու համար կարելի է օգտագործել ethtool -S ethX հրամանը, կարգավորումներն արեք նույն ethtool-ով (անհրաժեշտ է մեծացնել RX-բուֆերը (-G) և երբեմն անջատել որոշ offloads (-K)): Ընդհանուր խորհուրդը կարող է լինել, որ օգտագործեք առանձին պորտ՝ վերլուծվող տրաֆիկի ընդունման համար, եթե այդպիսի հնարավորություն կա, սա կնվազեցնի հFalse alarms, որոնք կապված են միաժամանակյա վերլուծողի պորտում մյուս տրաֆիկի ներկայության պատճառով: Եթե այսպիսի հնարավորություն չկա (օգտագործվում է մինի-համակարգիչ/NUC մեկ պորտով), ապա շատ ցանկալի է կարգավորել վերլուծվող տրաֆիկի գերակայությունը այլ տրաֆիկի նկատմամբ այդ устройстве, որը միանում է վերլուծիչին: Վիրտուալ միջավայրերի մասին պետք է լինել զգույշ և իմանալ՝ ինչպես գտնել փաթեթի բաժանումները ֆիզիկական պորտից սկսած մինչև վիրտուալ մեքենայի ներսում գտնվող հավելվածը:

Հոսքի արտադրություն և ընդունում հոսթի ներսում

TSDuck-ի նախապատրաստման առաջին քայլով մենք կարտադրենք և կընդունենք տրաֆիկը մեկ հոսթում՝ օգտագործելով netns:

Պատրաստում ենք միջավայրը:

ip netns add P #ստեղծում ենք netns P, որտեղ կկատարվի տրաֆիկի վերլուծություն
ip link add type veth #ստեղծում ենք veth-զույգ - veth0-ն թողնում ենք netns-ում ըստ ծագման (այս ինտերֆեյսում կարտադրվի տրաֆիկ)
ip link set dev veth1 netns P #veth1 - տեղափոխում ենք netns P (այս ինտերֆեյսում կլինի տրաֆիկի ընդունում)
ip netns exec P ifconfig veth1 192.0.2.1/30 up #բարձրացրեք IP-ն veth1-ում, կարևոր չէ այսպիսին թե ինչպիսին
ip netns exec P ip ro add default via 192.0.2.2 #կարգավորում ենք կանխորոշված երթուղին netns P-ի ներսում
sysctl net.ipv6.conf.veth0.disable_ipv6=1 #անջատում ենք IPv6-ը veth0-ի վրա - սա արվում է, որպեսզի TX հաշվետվությունում չմուտք գործի այլազան աղբյուր
ifconfig veth0 up #բարձրացնում ենք veth0 ինտերֆեյսը
ip route add 239.0.0.1 dev veth0 #ստեղծում ենք երթուղի, որպեսզի OS-ը ուղղի տրաֆիկը 239.0.0.1 ի veth0 կողմը

Միջավայրը պատրաստ է։ Ներդնում ենք տրաֆիկի վերլուծիչը:

ip netns exec P tsp --realtime -t 
 -I ip 239.0.0.1:1234 
 -P continuity 
 -P bitrate_monitor -p 1 -t 1 
 -O drop

որտեղ «-p 1 -t 1» նշանակում է, որ պետք է հաշվարկել բիտրեյթը յուրաքանչյուր վայրկյան և ցուցաբերել բիտրեյթի մասին տեղեկատվություն ամեն մեկրոպյակ
Շարունակել է տրաֆիկի արտադրությունը 10 Մբիթ/ս արագությամբ:

tsp -I craft 
 -P regulate -b 10000000 
 -O ip -p 7 -e --local-port 6000 239.0.0.1:1234

որտեղ «-p 7 -e» նշանակում է, որ պետք է 7 TS փաթեթը հավաքել 1 IP փաթեթի մեջ և անել դա խստորեն (-e), այսինքն՝ միշտ սպասել 7 TS փաթեթից նախորդ պրոցեսորից IP փաթեթի ձևավորման համար:

Վերլուծիչը սկսում է նախատեսված հաղորդագրությունները ցուցադրել:

* 2020/01/03 14:55:44 - bitrate_monitor: 2020/01/03 14:55:44, TS bitrate: 9,970,016 bits/s
* 2020/01/03 14:55:45 - bitrate_monitor: 2020/01/03 14:55:45, TS bitrate: 10,022,656 bits/s
* 2020/01/03 14:55:46 - bitrate_monitor: 2020/01/03 14:55:46, TS bitrate: 9,980,544 bits/s

Հիմա ավելացնում ենք մի քիչ դրոպ:

ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROP

և հայտնվում են հետևյալ նմանակի հաղորդագրություններ:

* 2020/01/03 14:57:11 - continuity: packet index: 80,745, PID: 0x0000, missing 7 packets
* 2020/01/03 14:57:11 - continuity: packet index: 83,342, PID: 0x0000, missing 7 packets 

ինչը սպասելի էր: Շուտափույթ բացում ենք փաթեթների կորուստը (ip netns exec P iptables -F) և փորձում ենք բարձրացնել գեներատորի битрейт-ը մինչև 100Մբիտ/վրկ: Վերլուծիչը հաղորդում է բազմաթիվ CC-սխալներ և մոտ 75 Մբիտ/վրկ փոխարեն 100: Փորձելով պարզել, ով է մեղավոր՝ գեներատորը, թե խնդիրը նրանում չէ, դրա համար запускаем фиксированное количество пакетов (700000 TS-пакетов = 100000 IP-пакетов):

# ifconfig veth0 | grep TX
       TX packets 151825460  bytes 205725459268 (191.5 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# tsp -I craft -c 700000 -P regulate -b 100000000 -P count -O ip -p 7 -e --local-port 6000 239.0.0.1:1234
* count: PID    0 (0x0000):    700,000 packets
# ifconfig veth0 | grep TX
        TX packets 151925460  bytes 205861259268 (191.7 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Ինչպես երևում է, բերվել է հենց 100000 IP-пакетов (151925460-151825460): Այնպես որ, հասկանում ենք, ինչ է կատարվում վերլուծիչում, դրա համար сравниваем со счётчиком RX на veth1, он строго равен счётчику TX на veth0, далее смотрим что происходит на уровне сокета:

# ip netns exec P cat /proc/net/udp                                                                                                           
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode ref pointer drops             
  133: 010000EF:04D2 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 72338 2 00000000e0a441df 24355 

Ահա այստեղ մատնանշվում է դրոպերի քանակը = 24355: TS-пакетов-ում դա 170485 կամ 24.36% 700000-ից, այնպես որ տեսնում ենք, որ այդ 25%-ը կորած битрейт-ի մեր իմաստով դրոպերն են UDP-сокете: UDP-сокете-ում դրոպերը սովորաբար առաջանում են բուֆերի պակասից, նայում ենք, թե ինչ ծավալի բուֆեր ունի ՝ ըստ էության, և առավելագույն բուֆերի չափը:

# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992

Դրա հետևանքով, եթե ծրագրերը հստակ չխնդրեն բուֆերների չափը, սոկետները ստեղծվում են 208 Կբ չափով բուֆերով, բայց եթե խնդրեն ավելի շատ, ապա այնուամենայնիվ չեն ստանա խնդրածը: Չնայած, որ tsp-ի համար IP-մտքում կարելի է սահմանել բուֆերի չափս (—buffer-size), նրա տվյալների բուֆերն չենք հպվում, այլ ընդամենը կարգավորում ենք սոկետի առավելագույն չափը և նշում բուֆերի չափը՝ tsp аргумենտներով:

sysctl net.core.rmem_max=8388608
ip netns exec P tsp --realtime -t -I ip 239.0.0.1:1234 -b 8388608 -P continuity -P bitrate_monitor -p 1 -t 1 -O drop

Այսպիսի բուֆերային կարգավորումով այժմ հաղորդվող битрейт-ը կազմում է մոտ 100Մբիտ/վրկ, CC-սխալներ չկան:

CPU սպառումը ինչպես նաև tsp ծրագրի կողմից: i5-4260U CPU @ 1.40GHz-ի մեկ ядրի համար, 10Մբիտ/վրկ հոսքի վերլուծության համար պահանջվում է 3-4% CPU, 100 Մբիտ/վրկ — 25%, 200Մբիտ/վրկ — 46%: Փաթեթների կորուստի % սահմանելով CPU-ի բեռը զուտ չի ավելանում (բայց կարող է նվազել):

Բարձր արտադրողական մեքենաների մեջ առանց խնդիրներ ստեղծելու հաջողվում էր արտադրել և վերլուծել հոսքեր նույնպես 1Գբ/վրկ-ից:

Բ reais сетевые карты тестирование

veth-զույգով փորձարկումից հետո հարկավոր է վերցնել երկու հոսանք կամ մեկ հոսանքի երկու պորտ, միացնել պորտերը իրար, մեկում սկսել գեներատոր, մյուսում՝ վերլուծիչ: Այստեղ անսպասելի բաներ տեղի չունեցան, բայց իրականում ամեն բան կախված է տեխնիկայից, որքան իսպաներեն ընտրանքային է, այնքան ավելի հետաքրքիր կլինի այստեղ:

Ամփոփման տված տեղեկությունները դիտարկման համակարգով (Zabbix)

tsp-ում չունի որևէ machine-readable API, օրինակ՝ SNMP կամ նման մի բան: CC հաղորդագրությունները անհրաժեշտ է հավաքել գոնե 1 վարկյանի համար (բարձր կորուստների դեպքում դրանք կարող են լինել հարյուրների/հազարավոր/տասնյակ հազարավոր վարկյան մեկ, կախված битрейт-ից):

Այսպիսով, CC-գործողությունների և բիթռեյթի մասին տեղեկատվություն պահպանելու և գրաֆիկներ նկարելու համար հնարավոր են հետևյալ տարբերակները:

  1. Վերլուծել և հավաքագրել (CC-ի միջոցով) tsp-ի դարձրը, սովորական ձևի փոխակերպումը:
  2. Բազմակողմանի լրացնել tsp-ը և/կամ բիթռեյթի մոնիթոր և շարունակական ծրագրակազմերը, որպեսզի արդյունքը ստացվի մեքենայական ընթերցման ձևով, որ հնարավոր լինի մոնիթորինգի համակարգում:
  3. Հ écrire ինքնուրույն ծրագիր tsduck գրադարանի վերևում:

Ակնհայտ է, որ աշխատանքային ծախսերի տեսանկյունից 1-ին տարբերակը ամենահեշտն է, հատկապես учитывая, что сам tsduck написан на низкоуровневом (по современным меркам) языке (C++)

Սովորական մի զբաղվածության միջավայրը bash-ում ցույց տվեց, որ 10 Մբիտ/վ տվյալների և 50% պակասի դեպքում (վատագույն տարբերակը), bash-ի պրոցեսը 3-4 անգամ ավելի CPU Է սպառում, քան tsp-ը: Այդպիսի զարգացումը անընդունելի է: Անշուշտ, այս պրոտոտիպի միտումն ниже:

Լապշա բաշում

#!/usr/bin/env bash

missingPackets=0
ccErrorSeconds=0
regexMissPackets='^* (.+) - continuity:.*missing ([0-9]+) packets$'
missingPacketsTime=""

ip netns exec P tsp --realtime -t -I ip -b 8388608 "239.0.0.1:1234" -O drop -P bitrate_monitor -p 1 -t 1  -P continuity 2>&1 | 
while read i
do
    #line example:* 2019/12/28 23:41:14 - continuity: packet index: 6,078, PID: 0x0100, missing 5 packets
    #line example 2: * 2019/12/28 23:55:11 - bitrate_monitor: 2019/12/28 23:55:11, TS bitrate: 4,272,864 bits/s
    if [[ "$i" == *continuity:* ]] 
    then
        if [[ "$i" =~ $regexMissPackets ]]
        then
            missingPacketsTimeNew="${BASH_REMATCH[1]}" #timestamp (seconds)
            if [[ "$missingPacketsTime" != "$missingPacketsTimeNew" ]] #new second with CC error
            then
                ((ccErrorSeconds += 1))
            fi
            missingPacketsTime=$missingPacketsTimeNew
            packets=${BASH_REMATCH[2]} #TS missing packets
            ((missingPackets += packets))
        fi
    elif [[ "$i" == *bitrate_monitor:* ]]
    then
        : #...
    fi
done

Բացի նրանից, որ դա աշխատում է անթույլատրելի դանդաղ, բաշում կան նորմալ թելեր, բաշ աշխատանքները ինքնուրույն պրոցեսներ են և պետք է կատարել մի հինգերորդ հերթով քիչ պակաս: Այսպիսով, bash-ը թողեց հանգիստ և որոշվեց գրել wrapper (ապահով և հավաքագրող) golang-ում: CPU-ի սպառման նման կոդը golang-ում 4-5 անգամ քիչ է կախված ամենամեծ tsp պրոցեսից: Wrapper-ի արագացումը փոխարինելով bash-ը golang-ով մոտ 16 անգամ դարձավ և ընդհանուր արդյունքը ընդունելի է (CPU-ի ավելաքանակը 25% ամենափոքր իրավիճակում): Նախնական ֆայլը golang-ում գտնվում է: այստեղ.

Wrapper-ի գործարկում

Wrapper-ի գործարկման համար պարզ սերվիսի ձևանմուշ է պատրաստվել systemd-ի համար (այստեղ). Հնարավոր է, որ wrapper-ը կոմպիլացվել է բինարային ֆայլի (go build tsduck-stat.go) մեջ, որը տեղադրված է /opt/tsduck-stat/: Հնարավոր է, որ օգտագործվում է golang, որը աջակցում է monotonic ժամացույցի (>=1.9):

Ապահովելու համար, որ ծառայության օրինակ ստեղծելու համար պետք է կատարեք systemctl enable tsduck-stat@239.0.0.1:1234 հրամանը, ապա սկսել systemctl start tsduck-stat@239.0.0.1:1234 միջոցով:

Zabbix-ի հայտնաբերում

Որպեսզի zabbix-ը կարողանա հայտնաբերել աշխատող ծառայությունները, պատրաստել է խմբերի ցուցակի գեներատոր (discovery.sh), որը Zabbix-ի յուրօրինակ թույլտվության ձևն է, ենթադրվում է, որ այն տեղադրված է նույն տեղում — /opt/tsduck-stat-ում: Ձևավորելու համար հայտնաբերման zabbix-agent-ի միջոցով, պետք է ավելացնել .conf ֆայլ zabbix-agent-ի կոնֆիգուրացման տարրերում, որպեսզի ավելացնել user-parametրը:

Zabbix-ի ձևանմուշ

Ստեղծված ձևանմուշը (tsduck_stat_template.xml) պարունակում է ավտո-հայտնաբերման կանոն, տվյալների տարրերի, գրաֆիկների և առաջացումների նախատիպեր:

Հակիրճ վերահսկիչ ցուցակ (նվազագույնը, եթե մեկ անձ ուզում է օգտագործել)

  1. Հավաստիանալ, որ tsp-ն չդորաբերում բռնկումներ «հիանալի» պայմաններում (աստվածաշնչները և վերլուծողը միանգամայն ուղղակիորեն լուծված են), եթե կան բռնկումներ, տեսեք համար 2 կամ այդ մասին հոդվածը:
  2. Արտահանել մաքսիմալ սոկետի բուֆերի (net.core.rmem_max=8388608) կարգավորումը:
  3. Կոմպիլացնել tsduck-stat.go (go build tsduck-stat.go):
  4. Տրանսֆերել ծառայության շաբլոնը դեպի /lib/systemd/system:
  5. Անչափել ծառայությունները systemctl-ով, ստուգել, որ թվիչները հայտնվում են (grep «» /dev/shm/tsduck-stat/*): Ծառայությունների քանակը լինում է մուլտիկաստական հոսքերի քանակով: Այստեղ հնարավոր է, որ պետք լինի ստեղծել երթուղի դեպի մուլտիկաստային խումբ, հնարավոր է отключить rp_filter կամ ստեղծել երթուղի դեպի source ip:
  6. Սկսել discovery.sh, համոզվել, որ այն ստեղծում է json:
  7. Բեռնել zabbix-ագենց, նորից սկսեք zabbix-ագենտը.
  8. Բեռնել շաբլոնը zabbix-ում, կիրառել այն այն հոստի վրա, որտեղ կատարվում է մոնիտորինգ և տեղադրված է zabbix-agent, սպասել մոտ 5 րոպե, դիտել, թե արդյոք նոր տվյալների տարրեր, գալարներ և հեծանիվներ են հայտնվում:

Արդյունք

TSDuck-ի օգտագործումը IP(TS)-կայքերի մոնիտորինգի համար

Փաթսյակներ կորցնելու խնդրի համար դա գրեթե բավարար է, առնվազն դա ավելի լավ է, քան մոնիտորինգի բացակայությունը:

Իրոք, CC-«կորուստները» կարող են առաջանալ վիդեո ֆրագմենտների միացման ժամանակ (ինչպես ինձ հայտնի է, այդ գործելակերպը կիրառում են տեղի հեռուստադիտարաններում ՌԴ-ում, այսինքն, CC-հաշվիչի հաշվումներ չի արվում), սա պետք է հիշել: նվիրված լուծումներում այս խնդիրը մասնակիորեն շրջանցվում է SCTE-35 լոգոների հայտնաբերումով (եթե դրանք ավելացվում են հոսքի արտադրողի կողմից):

Տրանսպորտի որակի մոնիտորինգի տեսանկյունից, չի хватает jitter( IAT) մոնիտորինգի, քանի որ հեռուստատեսային սարքերը (ապա լինի մոդուլատորներ կամ վերջնական սարքեր) ունեն այս պարամետրի պահանջներ և միշտ չի կարելի ամբարշնել jitter բուֆերը անվերջ: Իսկ jitter-ը կարող է խաթարվել, երբ տեղափոխման ժամանակ օգտագործվում են մեծ բուֆերներ ունեցող սարքավորումներ և QoS-ն, որը նախատեսված է նման real-time երթևեկություն փոխանցելու համար, լավ չի կարգավորվում կամ բավարար չի կարգավորվել:

Ընտանիք: habr.com

Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով 🔥 Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster