Multimedia Network Protocols (โปรโตคอลเครือข่ายมัลติมีเดีย)

1. บทนำ: โปรโตคอลมัลติมีเดียในเครือข่าย

1.1 ความสำคัญของ Real-time Communication

Multimedia Network Protocols คือกลุ่มของโปรโตคอลที่ออกแบบมาเฉพาะสำหรับการส่งข้อมูลเสียง (Voice) และวิดีโอ (Video) แบบ real-time ผ่านเครือข่าย IP ซึ่งแตกต่างจากการส่งข้อมูลทั่วไปตรงที่ต้องการ ความหน่วงต่ำ (Low Latency) และ ความต่อเนื่อง (Continuity) มากกว่าความถูกต้องสมบูรณ์ 100%

ลักษณะพิเศษของ Real-time Traffic:

1.2 ภาพรวมของ Protocol Stack มัลติมีเดีย

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#282828', 'mainBkg': '#282828', 'nodeBorder': '#928374', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'attributeBackgroundColorEven': '#3c3836', 'attributeBackgroundColorOdd': '#504945'}}}%%
flowchart TD
    subgraph APP["Application Layer (ชั้นแอปพลิเคชัน)"]
        A1["🎤 Voice/Video Application - Softphone, Video Conferencing"]
    end
    subgraph SIG["Signaling Protocols (โปรโตคอลส่งสัญญาณ)"]
        S1["SIP - Session Initiation Protocol"]
        S2["H.323 - ITU-T Standard"]
    end
    subgraph MEDIA["Media Transport (การส่งข้อมูลสื่อ)"]
        M1["RTP - Real-time Transport Protocol"]
        M2["SRTP - Secure RTP"]
        M3["RTCP - RTP Control Protocol"]
    end
    subgraph TRANS["Transport Layer (ชั้น Transport)"]
        T1["UDP - User Datagram Protocol"]
    end
    subgraph NET["Network Layer (ชั้น Network)"]
        N1["IP - Internet Protocol"]
    end

    APP --> SIG
    SIG --> MEDIA
    MEDIA --> TRANS
    TRANS --> NET

    style APP fill:#458588,color:#ebdbb2,stroke:#83a598
    style SIG fill:#d79921,color:#282828,stroke:#fabd2f
    style MEDIA fill:#98971a,color:#ebdbb2,stroke:#b8bb26
    style TRANS fill:#cc241d,color:#ebdbb2,stroke:#fb4934
    style NET fill:#689d6a,color:#ebdbb2,stroke:#8ec07c

1.3 ประวัติความเป็นมาของ Multimedia Protocols

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
flowchart TB
    subgraph ERA1["ยุคที่ 1: ต้นกำเนิด (1990s)"]
        E1A["1996 - H.323 v1 - ITU-T Standard"]
        E1B["1996 - RTP RFC 1889 - IETF Standard"]
    end
    subgraph ERA2["ยุคที่ 2: SIP (Late 1990s - 2000s)"]
        E2A["1999 - SIP RFC 2543 - เริ่มต้น SIP"]
        E2B["2002 - SIP RFC 3261 - Stable Version"]
        E2C["2004 - SRTP RFC 3711 - Secure RTP"]
    end
    subgraph ERA3["ยุคที่ 3: WebRTC & Modern (2010s+)"]
        E3A["2012 - WebRTC - Browser-based VoIP"]
        E3B["2018 - SIP over WebSocket - Unified Comms"]
        E3C["2020+ - Video Conferencing - Zoom, Teams, Meet"]
    end

    ERA1 --> ERA2 --> ERA3

    style ERA1 fill:#504945,color:#ebdbb2,stroke:#665c54
    style ERA2 fill:#3c3836,color:#ebdbb2,stroke:#504945
    style ERA3 fill:#282828,color:#ebdbb2,stroke:#3c3836

2. RTP — Real-time Transport Protocol

2.1 ความหมายและหลักการทำงาน

RTP (Real-time Transport Protocol) คือโปรโตคอลมาตรฐานสำหรับการส่งข้อมูลเสียงและวิดีโอแบบ real-time ผ่านเครือข่าย IP กำหนดในมาตรฐาน RFC 3550 โดย IETF

RTP ทำงานบน UDP เป็นหลัก เนื่องจาก:

2.2 โครงสร้าง RTP Packet Header

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#d79921'}}}%%
packet-beta
    0-1: "V=2"
    2: "P"
    3: "X"
    4-7: "CC"
    8: "M"
    9-15: "PT (Payload Type)"
    16-31: "Sequence Number (เลขลำดับ)"
    32-63: "Timestamp (ตราเวลา)"
    64-95: "SSRC (Synchronization Source)"
    96-127: "CSRC (Contributing Source) [optional]"
    128-159: "Extension Header [optional]"
    160-191: "Payload Data (ข้อมูลเสียง/วิดีโอ)"

คำอธิบายฟิลด์สำคัญใน RTP Header:

2.3 RTCP — RTP Control Protocol

RTCP (RTP Control Protocol) เป็นโปรโตคอลคู่กับ RTP ทำหน้าที่ตรวจสอบคุณภาพการส่งข้อมูล โดยปกติจะส่งบน Port ถัดจาก RTP +1

ประเภท RTCP Packet ชื่อเต็ม หน้าที่
SR (200) Sender Report สถิติจากผู้ส่ง: packets sent, bytes sent, timestamp
RR (201) Receiver Report สถิติจากผู้รับ: packet loss, jitter, delay
SDES (202) Source Description ข้อมูลผู้ส่ง: CNAME, NAME, EMAIL
BYE (203) Goodbye แจ้งการสิ้นสุด session
APP (204) Application-Defined ข้อมูล custom ของแอปพลิเคชัน

2.4 การคำนวณ RTP Timestamp

RTP Timestamp ไม่ได้แสดงเวลาจริง แต่เป็น จำนวน sampling unit นับจากจุดเริ่มต้น

สูตรคำนวณ Timestamp:

TRTP = Tstart + t × fs

โดยที่:

ตัวอย่างการคำนวณ:

สมมติใช้ codec G.711 (PCMU) ที่มี sampling rate 8,000 Hz และส่งข้อมูลทุก 20ms (0.02 วินาที)

Timestamp increment per packet = 0.02 × 8000 = 160 samples

การคำนวณ Jitter (ความไม่สม่ำเสมอของ Delay):

J = J + | D ( i - 1 , i ) | - J 16

โดยที่ D(i-1, i) คือความต่างของ relative transit time ระหว่างแพ็กเก็ตสองชุด

2.5 ตัวอย่าง Code: RTP Packet Parser ใน Python

import struct
import socket
import time
from dataclasses import dataclass
from typing import Optional

@dataclass
class RTPPacket:
    """
    โครงสร้างข้อมูลสำหรับ RTP Packet
    ตาม RFC 3550 - Real-time Transport Protocol
    """
    version: int          # รุ่น RTP (ควรเป็น 2)
    padding: bool         # มี padding หรือไม่
    extension: bool       # มี extension header หรือไม่
    marker: bool          # marker bit
    payload_type: int     # ประเภทของ codec
    sequence_number: int  # เลขลำดับแพ็กเก็ต
    timestamp: int        # RTP timestamp
    ssrc: int             # Synchronization Source ID
    payload: bytes        # ข้อมูลเสียง/วิดีโอ


def parse_rtp_packet(data: bytes) -> Optional[RTPPacket]:
    """
    แปลง raw bytes เป็น RTP Packet object
    
    Args:
        data: ข้อมูล bytes ของ RTP packet ที่รับมา
        
    Returns:
        RTPPacket object หากแปลงสำเร็จ, None หากข้อมูลไม่ถูกต้อง
    """
    # ตรวจสอบขนาดขั้นต่ำของ RTP header (12 bytes)
    if len(data) < 12:
        print(f"[ERROR] ข้อมูลสั้นเกินไป: {len(data)} bytes (ต้องการอย่างน้อย 12 bytes)")
        return None

    # แกะ RTP header (12 bytes แรก) ด้วย struct.unpack
    # Format: !BBHII = network byte order, 2 bytes, 2 bytes, 4 bytes, 4 bytes
    first_byte, second_byte, seq_num, timestamp, ssrc = struct.unpack('!BBHII', data[:12])

    # ดึงค่าจาก byte แรก
    version   = (first_byte >> 6) & 0x03   # bits 7-6
    padding   = bool((first_byte >> 5) & 0x01)   # bit 5
    extension = bool((first_byte >> 4) & 0x01)   # bit 4
    cc        = first_byte & 0x0F                 # bits 3-0 (CSRC count)

    # ดึงค่าจาก byte ที่สอง
    marker       = bool((second_byte >> 7) & 0x01)  # bit 7
    payload_type = second_byte & 0x7F               # bits 6-0

    # ตรวจสอบ version
    if version != 2:
        print(f"[WARNING] RTP Version ไม่ถูกต้อง: {version} (คาดหวัง 2)")
        return None

    # คำนวณตำแหน่งเริ่มต้นของ payload (ข้ามส่วน CSRC)
    header_length = 12 + (cc * 4)  # Header + CSRC identifiers
    payload = data[header_length:]

    return RTPPacket(
        version=version,
        padding=padding,
        extension=extension,
        marker=marker,
        payload_type=payload_type,
        sequence_number=seq_num,
        timestamp=timestamp,
        ssrc=ssrc,
        payload=payload
    )


def get_codec_name(payload_type: int) -> str:
    """
    แปลง Payload Type number เป็นชื่อ codec
    ตาม RFC 3551
    """
    # ตารางการแม็ปของ standard payload types
    codec_map = {
        0: "PCMU (G.711 µ-law, 8kHz)",
        3: "GSM (6.10, 8kHz)",
        4: "G.723 (8kHz)",
        8: "PCMA (G.711 A-law, 8kHz)",
        9: "G.722 (16kHz)",
        18: "G.729 (8kHz)",
        26: "JPEG Video",
        31: "H.261 Video",
        34: "H.263 Video",
        96: "Dynamic (ต้องดูจาก SDP)",  # 96-127 = dynamic
    }

    if 96 <= payload_type <= 127:
        return f"Dynamic Payload Type {payload_type} (ดูจาก SDP)"
    
    return codec_map.get(payload_type, f"Unknown PT={payload_type}")


def monitor_rtp_stream(host: str = "0.0.0.0", port: int = 5004, duration: int = 10):
    """
    ตรวจสอบและวิเคราะห์ RTP stream แบบ real-time
    
    Args:
        host: IP address ที่จะรับฟัง (0.0.0.0 = ทุก interface)
        port: UDP port สำหรับ RTP (ค่าเริ่มต้น 5004)
        duration: ระยะเวลาการตรวจสอบ (วินาที)
    """
    # สร้าง UDP socket สำหรับรับ RTP packets
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((host, port))
    sock.settimeout(1.0)  # timeout 1 วินาที

    print(f"🎧 กำลังตรวจสอบ RTP stream บน {host}:{port}")
    print(f"⏱️  ระยะเวลา: {duration} วินาที")
    print("-" * 60)

    # ตัวแปรสำหรับเก็บสถิติ
    packets_received = 0
    packets_lost = 0
    last_seq = None
    start_time = time.time()

    while time.time() - start_time < duration:
        try:
            data, addr = sock.recvfrom(4096)  # รับข้อมูลสูงสุด 4096 bytes
            packet = parse_rtp_packet(data)

            if packet:
                packets_received += 1

                # ตรวจสอบ packet loss โดยดู sequence number
                if last_seq is not None:
                    expected_seq = (last_seq + 1) % 65536  # wraps around ที่ 65535
                    if packet.sequence_number != expected_seq:
                        lost = (packet.sequence_number - expected_seq) % 65536
                        packets_lost += lost
                        print(f"  ⚠️  Packet loss! คาดว่า seq={expected_seq}, ได้รับ seq={packet.sequence_number}")
                        print(f"     สูญหายไป {lost} packet(s)")

                last_seq = packet.sequence_number

                # แสดงข้อมูล packet
                codec = get_codec_name(packet.payload_type)
                print(f"📦 Packet #{packets_received:4d} | "
                      f"Seq: {packet.sequence_number:5d} | "
                      f"TS: {packet.timestamp:10d} | "
                      f"SSRC: {packet.ssrc:08X} | "
                      f"Codec: {codec}")

        except socket.timeout:
            continue  # ไม่มีข้อมูลมาใน 1 วินาที, วนซ้ำ

    # สรุปสถิติ
    sock.close()
    total = packets_received + packets_lost
    loss_rate = (packets_lost / total * 100) if total > 0 else 0

    print("\n" + "=" * 60)
    print("📊 สรุปผลการตรวจสอบ RTP Stream")
    print(f"   รับได้:    {packets_received} packets")
    print(f"   สูญหาย:   {packets_lost} packets")
    print(f"   Loss Rate: {loss_rate:.2f}%")
    print(f"   คุณภาพ:   {'✅ ดี' if loss_rate < 1 else '⚠️ ปานกลาง' if loss_rate < 5 else '❌ แย่'}")


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # จำลองการแปลง RTP packet จาก raw bytes
    # สร้าง RTP packet ตัวอย่างด้วยมือ
    sample_rtp = struct.pack('!BBHII',
        0x80,      # V=2, P=0, X=0, CC=0
        0x00,      # M=0, PT=0 (PCMU)
        1234,      # Sequence Number
        12345678,  # Timestamp
        0xDEADBEEF # SSRC
    ) + b'\x00' * 160  # 160 bytes of audio payload (20ms of G.711)

    print("=== ทดสอบ RTP Packet Parser ===")
    packet = parse_rtp_packet(sample_rtp)
    if packet:
        print(f"Version:         {packet.version}")
        print(f"Payload Type:    {packet.payload_type}{get_codec_name(packet.payload_type)}")
        print(f"Sequence Number: {packet.sequence_number}")
        print(f"Timestamp:       {packet.timestamp}")
        print(f"SSRC:            {packet.ssrc:08X}")
        print(f"Payload Size:    {len(packet.payload)} bytes")

2.6 Codec ที่นิยมใช้กับ RTP

Codec Payload Type Sampling Rate Bitrate ใช้สำหรับ
G.711 PCMU 0 8 kHz 64 kbps VoIP คุณภาพ telephony
G.711 PCMA 8 8 kHz 64 kbps VoIP คุณภาพ telephony (A-law)
G.722 9 16 kHz 64 kbps HD Voice, Wideband
G.729 18 8 kHz 8 kbps VoIP ประหยัด bandwidth
G.723.1 4 8 kHz 5.3/6.3 kbps Low bandwidth VoIP
Opus Dynamic 8-48 kHz 6-510 kbps Modern WebRTC, ยืดหยุ่นสูง
H.264 Dynamic - Variable Video conferencing
VP8 Dynamic - Variable WebRTC video

3. SRTP — Secure Real-time Transport Protocol

3.1 ความจำเป็นของการรักษาความปลอดภัย RTP

RTP ดั้งเดิมไม่มีการเข้ารหัสข้อมูล ทำให้เสี่ยงต่อ:

SRTP (Secure RTP) กำหนดในมาตรฐาน RFC 3711 (2004) แก้ไขปัญหาเหล่านี้โดยเพิ่ม:

3.2 สถาปัตยกรรม SRTP

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
flowchart TB
    subgraph SENDER["ฝั่งผู้ส่ง (Sender)"]
        P1["🎤 Audio/Video - Payload"]
        P2["RTP Packet - Assembly"]
        P3["AES Counter Mode - Encryption - (เข้ารหัส Payload)"]
        P4["HMAC-SHA1 - Authentication - (สร้าง MAC)"]
        P5["📤 SRTP Packet - (พร้อมส่ง)"]
    end
    subgraph KEYS["Key Management - (จัดการ Key)"]
        K1["Master Key - (128/256 bit)"]
        K2["Key Derivation - Function (KDF)"]
        K3["Session Keys: - • Cipher Key - • Salt Key - • Auth Key"]
    end
    subgraph RECEIVER["ฝั่งผู้รับ (Receiver)"]
        R1["📥 SRTP Packet"]
        R2["Replay Check - (ตรวจ seq window)"]
        R3["HMAC Verify - (ตรวจ integrity)"]
        R4["AES Decrypt - (ถอดรหัส)"]
        R5["🔊 Audio/Video - Output"]
    end

    P1 --> P2 --> P3 --> P4 --> P5
    K1 --> K2 --> K3
    K3 --> P3
    K3 --> P4
    P5 -.->|"Network"| R1
    R1 --> R2 --> R3 --> R4 --> R5

    style SENDER fill:#98971a,color:#ebdbb2,stroke:#b8bb26
    style KEYS fill:#d79921,color:#282828,stroke:#fabd2f
    style RECEIVER fill:#458588,color:#ebdbb2,stroke:#83a598

3.3 กระบวนการเข้ารหัส SRTP

SRTP ใช้ AES Counter Mode (AES-CTR) ในการเข้ารหัส payload:

การสร้าง Keystream:

IV = salt ( SSRC index ) E = AES k ( IV counter ) Ciphertext = Plaintext E

โดยที่:

การสร้าง Authentication Tag:

Auth Tag = HMAC-SHA1 ( ka , SRTP packet index ) [0:80]

โดยที่:

3.4 การแลกเปลี่ยน Key ด้วย SDES และ DTLS-SRTP

วิธีการแลกเปลี่ยน Key มาตรฐาน ความปลอดภัย ใช้ในระบบ
SDES (SDP Security Descriptions) RFC 4568 ปานกลาง (key ใน SDP) Legacy SIP systems
DTLS-SRTP RFC 5764 สูง (Perfect Forward Secrecy) WebRTC (บังคับใช้)
MIKEY (Multimedia Internet KEYing) RFC 3830 สูง IMS, Enterprise VoIP
ZRTP RFC 6189 สูงมาก (ไม่ต้องการ PKI) Zfone, Signal

3.5 SRTCP — Secure RTCP

SRTCP เป็นส่วนขยายของ SRTP สำหรับรักษาความปลอดภัยของ RTCP packets:


4. SIP — Session Initiation Protocol

4.1 ความหมายและบทบาท

SIP (Session Initiation Protocol) คือโปรโตคอลมาตรฐานสำหรับการ Signaling ในการสร้าง, ปรับเปลี่ยน, และยุติ multimedia session กำหนดในมาตรฐาน RFC 3261 SIP เป็น text-based protocol คล้าย HTTP ทำให้เข้าใจและ debug ได้ง่าย

SIP ทำหน้าที่ เฉพาะ Signaling — ไม่ส่งข้อมูลเสียงหรือวิดีโอ ข้อมูลจริงส่งผ่าน RTP/SRTP

4.2 องค์ประกอบของ SIP Architecture

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
flowchart TB
    subgraph CLIENTS["SIP Clients (User Agents)"]
        UA1["📱 Alice's SIP Phone - UA: sip:alice@example.com"]
        UA2["💻 Bob's Softphone - UA: sip:bob@example.com"]
    end
    subgraph SERVERS["SIP Servers"]
        PROXY["🔄 SIP Proxy Server - (ส่งต่อ requests)"]
        REG["📋 Registrar Server - (เก็บ location ของ UA)"]
        REDIR["↩️ Redirect Server - (แนะนำ route ใหม่)"]
        B2B["🔀 B2BUA - (Back-to-Back User Agent)"]
    end
    subgraph INFRA["Infrastructure"]
        DNS["🌐 DNS/ENUM - (ค้นหา SIP URI)"]
        DB["🗄️ Location Service - (IP: port ของ UA)"]
    end

    UA1 <-->|"SIP Signaling"| PROXY
    UA2 <-->|"SIP Signaling"| PROXY
    PROXY <--> REG
    PROXY <--> REDIR
    PROXY <--> B2B
    REG <--> DB
    PROXY <--> DNS

    UA1 <-.->|"RTP Media (Audio/Video)"| UA2

    style CLIENTS fill:#689d6a,color:#ebdbb2,stroke:#8ec07c
    style SERVERS fill:#458588,color:#ebdbb2,stroke:#83a598
    style INFRA fill:#504945,color:#ebdbb2,stroke:#665c54

4.3 SIP Messages

SIP ใช้ข้อความแบบ text ซึ่งแบ่งเป็น Requests และ Responses:

SIP Request Methods:

Method หน้าที่ RFC
INVITE ชวน/เริ่ม session RFC 3261
ACK ยืนยันการรับ final response RFC 3261
BYE ยุติ session RFC 3261
CANCEL ยกเลิก pending request RFC 3261
REGISTER ลงทะเบียน location กับ Registrar RFC 3261
OPTIONS ถาม capabilities RFC 3261
SUBSCRIBE subscribe to event RFC 3265
NOTIFY แจ้ง event ให้ subscriber RFC 3265
REFER ให้ UA โทรหาคนอื่น (call transfer) RFC 3515
MESSAGE ส่ง instant message RFC 3428

SIP Response Codes:

Code Range ความหมาย ตัวอย่าง
1xx Provisional (กำลังดำเนินการ) 100 Trying, 180 Ringing
2xx Success (สำเร็จ) 200 OK
3xx Redirection (เปลี่ยนทาง) 302 Moved Temporarily
4xx Client Error (ผิดพลาดจากฝั่ง client) 403 Forbidden, 404 Not Found
5xx Server Error (ผิดพลาดจาก server) 500 Server Internal Error
6xx Global Failure (ล้มเหลวทุกที่) 603 Decline

4.4 ขั้นตอนการโทร SIP (Call Flow)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
sequenceDiagram
    participant A as "📱 Alice (Caller)"
    participant P as "🔄 SIP Proxy"
    participant B as "💻 Bob (Callee)"

    Note over A,B: ขั้นตอนที่ 1: Registration (ลงทะเบียน)
    A->>P: REGISTER sip:proxy.example.com
    P-->>A: 200 OK

    Note over A,B: ขั้นตอนที่ 2: Call Setup (สร้างสาย)
    A->>P: INVITE sip:bob@example.com
    P->>B: INVITE sip:bob@example.com
    B-->>P: 100 Trying
    P-->>A: 100 Trying
    B-->>P: 180 Ringing 🔔
    P-->>A: 180 Ringing 🔔
    B-->>P: 200 OK
    P-->>A: 200 OK
    A->>P: ACK
    P->>B: ACK

    Note over A,B: ขั้นตอนที่ 3: Media Exchange (สนทนา)
    A-->>B: 🔊 RTP/SRTP Media Stream

    Note over A,B: ขั้นตอนที่ 4: Call Teardown (วางสาย)
    B->>P: BYE
    P->>A: BYE
    A-->>P: 200 OK
    P-->>B: 200 OK

4.5 SDP — Session Description Protocol

SIP ใช้ SDP (Session Description Protocol) ตาม RFC 4566 เพื่อบอกรายละเอียด session เช่น codec, port, IP address

ตัวอย่าง SDP Offer จาก Alice:

v=0
o=alice 2890844526 2890844527 IN IP4 192.168.1.10
s=Phone Call
c=IN IP4 192.168.1.10
t=0 0
m=audio 49170 RTP/AVP 0 8 18
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=ptime:20
a=sendrecv

คำอธิบาย SDP fields:

4.6 SIP Security Issues

SIP มีช่องโหว่ด้านความปลอดภัยหลายประการ:

1. SIP Digest Authentication:

SIP ใช้ HTTP Digest Authentication ตาม RFC 3261:

HA1 = MD5 ( username : realm : password ) HA2 = MD5 ( method : URI ) Response = MD5 ( HA1 : nonce : HA2 )

ปัญหา: ใช้ MD5 ซึ่งปัจจุบันถือว่า ไม่ปลอดภัย (สามารถ brute-force ได้) ควรใช้ SIP over TLS แทน

2. การส่ง SIP บน TLS:


5. H.323 — Multimedia Communication Protocol

5.1 ความหมายและประวัติ

H.323 คือมาตรฐานของ ITU-T (International Telecommunication Union) สำหรับระบบการสื่อสารมัลติมีเดียบนเครือข่าย packet-based ออกมาตั้งแต่ปี 1996 ก่อน SIP มาก H.323 เป็น suite ของโปรโตคอลที่ประกอบด้วยส่วนต่าง ๆ หลายชิ้น

5.2 องค์ประกอบของ H.323

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
flowchart TD
    H323["H.323 Suite - (ชุดโปรโตคอล)"]

    H323 --> TERM["📱 Terminal - (อุปกรณ์ปลายทาง)"]
    H323 --> GK["🔑 Gatekeeper - (ควบคุมการเข้าถึง)"]
    H323 --> GW["🌉 Gateway - (เชื่อม PSTN)"]
    H323 --> MCU["🎛️ MCU - (Multipoint Control Unit)"]

    H323 --> PROTOCOLS["โปรโตคอลภายใน"]
    PROTOCOLS --> H225["H.225.0 - Call Signaling - (TCP port 1720)"]
    PROTOCOLS --> H245["H.245 - Media Control - (capability exchange)"]
    PROTOCOLS --> H235["H.235 - Security"]
    PROTOCOLS --> H239["H.239 - Dual Video Stream"]

    H323 --> CODECS["Codecs ที่รองรับ"]
    CODECS --> AUDIO["เสียง: G.711, G.722, G.723.1, G.728, G.729"]
    CODECS --> VIDEO["วิดีโอ: H.261, H.263, H.264, H.265"]
    CODECS --> DATA["ข้อมูล: T.120 - (application sharing)"]

    style H323 fill:#d79921,color:#282828,stroke:#fabd2f
    style PROTOCOLS fill:#458588,color:#ebdbb2,stroke:#83a598
    style CODECS fill:#98971a,color:#ebdbb2,stroke:#b8bb26

5.3 การเปรียบเทียบ H.323 กับ SIP

คุณสมบัติ H.323 SIP
ผู้กำหนดมาตรฐาน ITU-T IETF
รูปแบบข้อความ Binary (ASN.1) Text (คล้าย HTTP)
ความซับซ้อน สูงมาก ปานกลาง
การ setup ช้า (หลาย round trips) เร็วกว่า
NAT Traversal ยาก ยากแต่มีทางออกมากกว่า
Scalability จำกัด ดีกว่า
Extensibility ยาก ง่ายกว่า
การใช้งานปัจจุบัน Legacy, ลดลง ครองตลาด
Interoperability ดี (ใช้มานาน) ดี (ecosystem ใหญ่)
ตัวอย่างใช้งาน ระบบ Video Conference เก่า PBX, softphone, WebRTC

5.4 ขั้นตอนการสร้าง H.323 Call

  1. Registration — Terminal ลงทะเบียนกับ Gatekeeper ด้วย RRQ/RCF (H.225 RAS)
  2. Admission — ขอ admission จาก Gatekeeper ด้วย ARQ/ACF
  3. Call Signaling — สร้าง TCP connection ไปยัง port 1720, ส่ง SETUP message (H.225)
  4. Capability Exchange — แลกเปลี่ยน codec capabilities ด้วย H.245 (TerminalCapabilitySet)
  5. Logical Channel Opening — เปิด channel สำหรับส่ง media (H.245 OpenLogicalChannel)
  6. Media Transfer — ส่งข้อมูลเสียง/วิดีโอผ่าน RTP
  7. Call Disconnect — ปิด logical channels, ส่ง ReleaseComplete

6. ช่องโหว่และการป้องกัน VoIP

6.1 ภัยคุกคามที่พบบ่อยใน VoIP

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
mindmap
    root((VoIP Threats\nภัยคุกคาม VoIP))
        Eavesdropping
            RTP Stream Capture
            SIP Message Interception
            Credential Theft
        Denial of Service
            SIP Flood
            RTP Flood
            Resource Exhaustion
        Fraud & Abuse
            Toll Fraud / SPIT
            Caller ID Spoofing
            Vishing attacks
        Man-in-the-Middle
            SIP Hijacking
            RTP Injection
            Registration Hijacking
        Quality Attacks
            Jitter Injection
            Packet Dropping
            Delay Attacks

6.2 การโจมตีแต่ละประเภท

6.2.1 RTP Eavesdropping (การดักฟัง)

เนื่องจาก RTP ปกติไม่เข้ารหัส ผู้โจมตีที่อยู่ในเครือข่ายเดียวกันสามารถ:

  1. ใช้ Wireshark capture แพ็กเก็ต UDP
  2. Filter ด้วย rtp หรือ udp.port >= 10000 && udp.port <= 20000
  3. ใช้ฟีเจอร์ Telephony > RTP > Stream Analysis ใน Wireshark
  4. บันทึกเป็นไฟล์เสียง WAV ได้โดยตรง

ตัวอย่าง Wireshark capture filter สำหรับ RTP:

udp && (udp.port >= 10000 && udp.port <= 65535)

6.2.2 SIP Registration Hijacking

ผู้โจมตีส่ง REGISTER message ปลอมเพื่อ overwrite location ของเหยื่อ:

REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/UDP attacker.evil.com:5060;branch=z9hG4bKnasty
From: "Bob" <sip:bob@example.com>;tag=hijack123
To: <sip:bob@example.com>
Contact: <sip:bob@attacker.evil.com>    ← แทนที่ด้วย IP ของผู้โจมตี
Expires: 3600
Content-Length: 0

ผลลัพธ์: สายโทรที่มาหา Bob จะถูกส่งไปยังผู้โจมตีแทน

6.2.3 VLAN Hopping & QoS Abuse

VoIP มักใช้ Voice VLAN แยกต่างหาก ผู้โจมตีสามารถ:

6.2.4 Toll Fraud (การโทรหลอกเอาเงิน)

ผู้โจมตีพยายาม brute-force SIP credentials เพื่อใช้ระบบโทรศัพท์โทรไปยังหมายเลขระหว่างประเทศ:

ความเสี่ยง (baht/hour) = Rcall × simultaneous calls × cost per min × 60

6.3 เครื่องมือวิเคราะห์ VoIP Security

6.3.1 Wireshark — วิเคราะห์ RTP/SIP

ขั้นตอนการวิเคราะห์ VoIP traffic ใน Wireshark:

  1. เปิด Wireshark และเลือก network interface
  2. เริ่ม capture ด้วยคำสั่ง filter:
    sip || rtp
    
  3. ไปที่เมนู Telephony > VoIP Calls
  4. เลือก call ที่ต้องการวิเคราะห์
  5. คลิก Flow เพื่อดู SIP signaling flow
  6. คลิก Player เพื่อฟังเสียง (หาก RTP ไม่ได้เข้ารหัส)

6.3.2 SIPp — Load Testing Tool

# ทดสอบ SIP server ด้วย INVITE flood
sipp -sn uac -d 30000 -l 10 -r 5 192.168.1.100:5060

# พารามิเตอร์:
# -sn uac  = ใช้ script สำหรับ UAC (caller)
# -d 30000 = duration ของแต่ละ call = 30 วินาที
# -l 10    = จำนวน calls พร้อมกันสูงสุด 10
# -r 5     = rate 5 calls ต่อวินาที

6.4 มาตรการป้องกัน VoIP

6.4.1 การใช้ SRTP และ TLS

# ตัวอย่าง: ตรวจสอบว่า SIP endpoint รองรับ SRTP หรือไม่
import socket
import ssl

def check_sip_tls_support(host: str, port: int = 5061) -> dict:
    """
    ตรวจสอบว่า SIP server รองรับ TLS หรือไม่
    
    Args:
        host: hostname หรือ IP ของ SIP server
        port: port (5061 สำหรับ SIP/TLS)
        
    Returns:
        dict ที่มีข้อมูล TLS certificate และการรองรับ
    """
    result = {
        "host": host,
        "port": port,
        "tls_supported": False,
        "cipher": None,
        "cert_subject": None,
        "cert_expiry": None,
        "error": None
    }
    
    try:
        # สร้าง SSL context
        context = ssl.create_default_context()
        context.check_hostname = False       # สำหรับ testing เท่านั้น
        context.verify_mode = ssl.CERT_NONE  # สำหรับ testing เท่านั้น
        
        # สร้าง TCP connection
        raw_sock = socket.create_connection((host, port), timeout=5)
        
        # Wrap ด้วย TLS
        tls_sock = context.wrap_socket(raw_sock, server_hostname=host)
        
        # ดึงข้อมูล TLS
        result["tls_supported"] = True
        result["cipher"] = tls_sock.cipher()
        
        cert = tls_sock.getpeercert()
        if cert:
            result["cert_subject"] = dict(
                x[0] for x in cert.get('subject', [])
            )
            result["cert_expiry"] = cert.get('notAfter')
        
        tls_sock.close()
        
    except ConnectionRefusedError:
        result["error"] = "Connection refused — อาจไม่รองรับ TLS"
    except ssl.SSLError as e:
        result["error"] = f"SSL Error: {e}"
    except Exception as e:
        result["error"] = f"Error: {e}"
    
    return result


def check_srtp_in_sdp(sdp_content: str) -> dict:
    """
    วิเคราะห์ SDP เพื่อตรวจสอบการรองรับ SRTP
    
    Args:
        sdp_content: ข้อมูล SDP ที่ได้รับจาก SIP INVITE/200 OK
        
    Returns:
        dict ที่มีผลการวิเคราะห์
    """
    lines = sdp_content.strip().split('\n')
    result = {
        "srtp_supported": False,
        "rtp_only": False,
        "crypto_suites": [],
        "media_ports": [],
        "codecs": []
    }
    
    for line in lines:
        line = line.strip()
        
        # ตรวจหา SRTP ใน media description
        # m=audio 5004 RTP/SAVP ... (SAVP = Secure AVP)
        if line.startswith('m='):
            parts = line.split()
            if len(parts) >= 3:
                protocol = parts[2]
                if 'SAVP' in protocol:  # Secure Audio/Video Profile
                    result["srtp_supported"] = True
                elif 'AVP' in protocol:  # ปกติ (ไม่ปลอดภัย)
                    result["rtp_only"] = True
                
                # เก็บ port
                if len(parts) >= 2:
                    try:
                        result["media_ports"].append(int(parts[1]))
                    except ValueError:
                        pass
        
        # ตรวจหา crypto suites (SDES)
        # a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:...
        elif line.startswith('a=crypto:'):
            parts = line.split()
            if len(parts) >= 3:
                result["crypto_suites"].append(parts[1])
        
        # ตรวจหา codec
        elif line.startswith('a=rtpmap:'):
            # a=rtpmap:0 PCMU/8000
            codec_part = line.split(':', 1)[1] if ':' in line else ''
            parts = codec_part.split()
            if len(parts) >= 2:
                result["codecs"].append(parts[1])
    
    return result


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # ทดสอบ SRTP detection ใน SDP
    sample_sdp = """v=0
o=alice 2890844526 2890844527 IN IP4 192.168.1.10
s=Secure Call
c=IN IP4 192.168.1.10
t=0 0
m=audio 5004 RTP/SAVP 0 8
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:d0RmdmcmVCspeEc3jek7Ti1iGqtq/sNJJx1S4jF0
a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=ptime:20
"""
    
    print("=== วิเคราะห์ SRTP ใน SDP ===")
    analysis = check_srtp_in_sdp(sample_sdp)
    print(f"รองรับ SRTP:        {analysis['srtp_supported']}")
    print(f"ใช้ RTP ปกติ:       {analysis['rtp_only']}")
    print(f"Crypto Suites:      {analysis['crypto_suites']}")
    print(f"Media Ports:        {analysis['media_ports']}")
    print(f"Codecs:             {analysis['codecs']}")
    
    if analysis['srtp_supported']:
        print("\n✅ ดี: Session นี้ใช้ SRTP — เสียงถูกเข้ารหัส")
    else:
        print("\n❌ เตือน: Session นี้ใช้ RTP ปกติ — เสียงไม่ได้เข้ารหัส!")

6.4.2 ตาราง Best Practices สำหรับ VoIP Security

มาตรการ รายละเอียด ระดับความสำคัญ
ใช้ SRTP เข้ารหัส media stream ทั้งหมด 🔴 สูงมาก
ใช้ SIP/TLS เข้ารหัส signaling 🔴 สูงมาก
VLAN Separation แยก Voice VLAN ออกจาก Data VLAN 🔴 สูงมาก
Strong Passwords ใช้รหัสผ่านที่ซับซ้อนสำหรับ SIP accounts 🔴 สูงมาก
Rate Limiting จำกัดจำนวน REGISTER/INVITE ต่อวินาที 🟠 สูง
Firewall/SBC ใช้ Session Border Controller 🟠 สูง
Fail2Ban สำหรับ SIP block IP ที่ login ผิดพลาดหลายครั้ง 🟠 สูง
Disable Unused Codecs จำกัดเฉพาะ codec ที่ต้องการ 🟡 ปานกลาง
QoS & DSCP Marking รับประกันคุณภาพเสียง 🟡 ปานกลาง
Log Analysis ตรวจสอบ CDR log หาพฤติกรรมผิดปกติ 🟡 ปานกลาง
NAT Traversal (STUN/TURN) แก้ปัญหา one-way audio 🟢 พื้นฐาน
Network Monitoring ตรวจสอบ VoIP traffic ด้วย RTCP 🟢 พื้นฐาน

6.4.3 Session Border Controller (SBC)

SBC (Session Border Controller) คืออุปกรณ์ที่ทำหน้าที่เป็น security gateway สำหรับ VoIP:

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#928374', 'lineColor': '#d5c4a1', 'background': '#282828', 'mainBkg': '#3c3836'}}}%%
flowchart LR
    subgraph EXTERNAL["Internet / Untrusted Zone"]
        EXT1["📱 Remote SIP Phone"]
        EXT2["☎️ External SIP Trunk"]
        EXT3["👿 Attacker"]
    end
    subgraph SBC_ZONE["Session Border Controller"]
        SBC["🛡️ SBC - • NAT Traversal - • Topology Hiding - • DoS Protection - • Media Transcoding - • Encryption Enforcement - • Rate Limiting"]
    end
    subgraph INTERNAL["Internal Network / Trusted Zone"]
        INT1["🖥️ SIP PBX Server"]
        INT2["💻 IP Phones"]
        INT3["📟 SIP Softphone"]
    end

    EXT1 <-->|"SIP/TLS + SRTP\n(encrypted)"| SBC
    EXT2 <-->|"SIP Trunk"| SBC
    EXT3 -->|"Attack traffic\n(blocked)"| SBC

    SBC <-->|"SIP (plaintext OK)\n+ RTP"| INT1
    INT1 <--> INT2
    INT1 <--> INT3

    style EXTERNAL fill:#cc241d,color:#ebdbb2,stroke:#fb4934
    style SBC_ZONE fill:#d79921,color:#282828,stroke:#fabd2f
    style INTERNAL fill:#98971a,color:#ebdbb2,stroke:#b8bb26

6.4.4 การตั้งค่า Fail2Ban สำหรับ SIP

# /etc/fail2ban/filter.d/asterisk.conf
# กฎสำหรับตรวจจับ SIP brute force

[Definition]
# ตรวจหา log patterns ที่บ่งบอกว่ามีการพยายาม login ผิดพลาด
failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Wrong password
            NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - No matching peer found
            NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Username/auth name mismatch
            SECURITY.* .*: Invalid SIP message from <HOST>

ignoreregex =

# /etc/fail2ban/jail.local
# [asterisk]
# enabled  = true
# port     = 5060,5061
# filter   = asterisk
# logpath  = /var/log/asterisk/messages
# maxretry = 5       ← ผิดพลาดได้ไม่เกิน 5 ครั้ง
# findtime = 21600   ← ภายใน 6 ชั่วโมง
# bantime  = 86400   ← แบนเป็นเวลา 24 ชั่วโมง

6.5 การใช้ Wireshark วิเคราะห์ VoIP

ขั้นตอนที่ 1: Capture SIP/RTP Traffic

# Capture ด้วย tcpdump บน Linux
sudo tcpdump -i eth0 -w voip_capture.pcap 'port 5060 or (udp and portrange 10000-20000)'

# พารามิเตอร์:
# -i eth0         = interface ที่ต้องการ capture
# -w voip_capture = บันทึกเป็นไฟล์ pcap
# port 5060       = SIP port
# portrange 10000-20000 = RTP port range ที่ใช้บ่อย

ขั้นตอนที่ 2: วิเคราะห์ใน Wireshark

Display Filter สำหรับ VoIP analysis:

1. ดู SIP calls ทั้งหมด:     sip
2. ดูเฉพาะ INVITE:           sip.Method == "INVITE"  
3. ดู SIP errors:             sip.Status-Code >= 400
4. ดู RTP stream:             rtp
5. ดู RTCP statistics:        rtcp
6. ดู SIP + RTP รวม:         sip || rtp
7. ดู SRTP (encrypted RTP):   srtp

ขั้นตอนที่ 3: วิเคราะห์ RTP Statistics

ไปที่ Wireshark menu: Telephony → RTP → RTP Streams

ข้อมูลที่ได้:


7. สรุปโดยรวม

Multimedia Network Protocols เป็นส่วนสำคัญของระบบการสื่อสารสมัยใหม่ โดยมีประเด็นสำคัญที่ควรจำ:

ด้านโปรโตคอลหลัก:

ด้านความปลอดภัย:

ความสัมพันธ์ระหว่าง Protocol:

Application (Softphone) 
    → ใช้ SIP/H.323 สำหรับ Signaling (negotiate codec, exchange IPs)
    → ใช้ RTP/SRTP สำหรับส่ง Media จริง ๆ
    → ใช้ RTCP เพื่อ monitor คุณภาพ
    → ทั้งหมดวิ่งบน UDP/IP

8. เอกสารอ้างอิง

  1. RFC 3550 — Schulzrinne, H., Casner, S., Frederick, R., & Jacobson, V. (2003). RTP: A Transport Protocol for Real-Time Applications. IETF.
    URL: https://tools.ietf.org/html/rfc3550

  2. RFC 3711 — Baugher, M., McGrew, D., Naslund, M., Carrara, E., & Norrman, K. (2004). The Secure Real-time Transport Protocol (SRTP). IETF.
    URL: https://tools.ietf.org/html/rfc3711

  3. RFC 3261 — Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., & Schooler, E. (2002). SIP: Session Initiation Protocol. IETF.
    URL: https://tools.ietf.org/html/rfc3261

  4. RFC 4566 — Handley, M., Jacobson, V., & Perkins, C. (2006). SDP: Session Description Protocol. IETF.
    URL: https://tools.ietf.org/html/rfc4566

  5. RFC 3551 — Schulzrinne, H., & Casner, S. (2003). RTP Profile for Audio and Video Conferences with Minimal Control. IETF.
    URL: https://tools.ietf.org/html/rfc3551

  6. ITU-T H.323 — International Telecommunication Union. (2009). Packet-based Multimedia Communications Systems. ITU-T Recommendation H.323.
    URL: https://www.itu.int/rec/T-REC-H.323

  7. RFC 5764 — McGrew, D., & Rescorla, E. (2010). Datagram Transport Layer Security (DTLS) Extension to Establish Keys for the Secure Real-time Transport Protocol (SRTP). IETF.
    URL: https://tools.ietf.org/html/rfc5764

  8. RFC 6189 — Zimmermann, P., Johnston, A., & Callas, J. (2011). ZRTP: Media Path Key Agreement for Unicast Secure RTP. IETF.
    URL: https://tools.ietf.org/html/rfc6189

  9. Stallings, W. (2017). Network Security Essentials: Applications and Standards (6th ed.). Pearson.

  10. Collier, M., & Endler, D. (2006). Hacking Exposed VoIP: Voice Over IP Security Secrets & Solutions. McGraw-Hill.

  11. Porter, T. (2006). Practical VoIP Security. Syngress.