2019年2月12日 星期二

SIP Header: Record-Route and Route

SIP 請求的過程,UAC 和每一个經過的 Proxy,攏會加一筆頂頭 Via 來紀錄自己。回應會照這Via 紀錄反過來送回。如果請求會建立 Dialog,Dialog 建立後就知道對方位址 (Contact),後續 Dialog 內請求就直送對方,免經過這些 Proxy。

Dialog 建立過程中經過的那些 Proxy 中,如果仍要參與後續 Dialog 內的 Transaction,在經手 Dialog 建立的請求時,加上一筆頂頭 Record-Route 紀錄自己。當請求到達 UAS 後,UAS 會將全部 Record-Route 按照順序紀錄成 Route Set,並複製到回應訊息。UAC 收到回應訊息時,將全部 Record-Route 依相反順序紀錄成 Route Set。之後 Dialog 內 (如 ACK、BYE、re-INVITE) 的請求,依 Route Set 順序產生 Route 信頭,並依此順序轉送。

在 Dialog 建立請求時,UAC 也可以事先設定 Route 信頭,例如 outbound proxy。

參數
  • lr (loose router):請求先照 Route 順序傳送,最後才是請求 URI。過程中 Proxy 收到後,移除應該是自己的頂頭 Route。和 loose router 相對的,是舊 SIP 的 strict routing,需要一開始把請求 URI 移為最尾的 Route,過程中一直把頂頭 Route 移到請求 URI 使用。有 lr 參數採用 loose routing,否則採用 strict routing。
  • r2=
  • ftag=
  • nat=

UAC 發請求有 Route Set 時,如果 Route Set 的第 1 个 URI 有 lr 參數,Request-URI 放 remote target URI,Route 封頭 按順序放 Route Set 並含所有參數。如果 Route Set 的第 1 个 URI 沒有 lr 參數,Request-URI 放第 1 个 Route Set 去除 Request-URI 不允許的參數,Route 封頭按順序放剩下的 Route Set 並含所有參數,最後再加上 remote target URI。

應用:

  • 作 NAT 的 proxy 需要持續作位址轉換
  • 作 accounting 的 proxy 需要知道何時 BYE 通話結束。

SIP REGISTER 可以有 Route,忽略 Record-Route。

參考來源
  1. http://lirobo.blogspot.tw/2010/10/sip-invite.html
  2. http://kamailio.org/docs/modules/stable/modules/rr.html
  3. http://tools.ietf.org/html/rfc3261

2019年2月9日 星期六

SIP Definitons

SIP 用詞定義

Dialog (對話)

兩個 UA 間持續一段時間的暫時 SIP 關係,由 INVITE transaction 建立,用一組 Call-ID、From tag、和 To tag 結合起來識別。在 RFC 2543 稱為 Call Leg。
  • 目前只有 INVITE 可以建立對話。
  • BYE transaction 結束對話。
  • Dialog 內 (in-dialog):由相同的 Call-ID、From tag、和 To tag 識別,每個 SIP 請求的 CSeq 是增加的。
    • re-INVITE (沒有 To tag 是要建立不同的 session)
    • INFO
  • out-of-dialog:沒有 To tag 就是 out-of-dialog 嗎?還是指不會建立 dialog 的 transaction?
  • REGISTER 請求不會建立 dialog,所以 Record-Route 沒作用。
SIP 訊息的部件,傳遞關於 SIP 訊息的資訊,由一系列信頭欄位組成。

Header Field (信頭欄位)

SIP 訊息裡信頭 (Header) 的部件。一個信頭欄位包含一個信頭欄位名稱和 0 個以上信頭欄位值,可重複信頭欄位名稱出現在多個信頭欄位行。一個信頭欄位行裡有多個信頭欄位值用「,」隔開。有些信頭欄位只能有一個信頭欄位值,而只會有一個信頭欄位行。

Header Field Value (信頭欄位值)

一個信頭欄位值是一個值;一個信頭欄位包含 0 個以上信頭欄位值。

Informational Response

跟 Provisional Response 相同。

Initiator, Calling Party, Caller (發話端):

雙端中為了建立一個新 session (和 dialog) 發出 INVITE 請求那一端。發話端
保有其發話端角色從送一開始 INVITE 建立 dialog 開始,直到 dialog 結束。

Invitation

一個 INVITE 請求。

Invitee, Invited User, Called Party, Callee (受話端)

雙端中為了建立一個新 session 接收 INVITE 請求那一端。受話端保有其受話端角色從收到 INVITE 開始直到建立的 dialog 結束。

Route Set

一份 proxy 位址表,傳送特定請求時按照順序經過。Route Set 可透過如 Record-Route 學習、由用戶或服務提供者人工設定、或其它非 SIP 機制等設定。

Server

一個 network element,接收請求並回送回應來提供服務。 Server 範例有 Proxy、UAS、redirect server、和 registrar。

參考來源

RFC3261 §6

SDP

SDP (Session Description Protocol) 為了 session 發布、session 邀請、和其它形式多媒體 session 發起來描述多媒體 session。

SDP 定義在 RFC 4566 廢棄 RFC 2327RFC 3266

o=

<sess-version> 是 this session description 的版本號碼,用途 up to the creating tool,只要當 a modification is made to the session data 時要增加,建議使用 NTP 格式 timestamp。

應用

...
...

延伸閱讀

  • SDP simcap (RFC 3407 SDP Simple Capability Declaration)
  • RFC 4040 CLEARMODE
  • vbd

2019年1月19日 星期六

pcap 封包擷取過濾式

pcap 封包擷取過濾式 (filter expression) 用在 tcpdumpWireshark (TShark)、Dumpcap 等程式,在擷取階段就篩選封包。其基本表示式 (primitive) 至少會有一個以上前置限定詞 (qualifier),然後可能會有一個數字或名稱的 id。

限定詞可大致分類成通訊協定 (proto)、傳送方向 (dir)、類型 (type) 三種:
  • type:說明 id 是指什麼,未指明預設是 host
    • host host:位址或主機名稱,如果沒指明 proto 是指 IPv4 或 IPv6 的位址或主機名稱。
    • net net [mask netmask] 或 net net/len:IPv4 或 IPv6 位址、subnet,可指明 netmask。
    • port port:TCP 或 UDP 的通訊埠。
    • portrange port1-port2:TCP 或 UDP 通訊埠的範圍。
  • dir:限定方向
    • srcdstsrc or dst (預設)、和 src and dst
    • proto wlan 限定:rataaddr1addr2addr3addr4dir
  • proto:限定協定,有 etheripip6arprarptcpudp 等,未指明則預設所有跟 type 能一致的協定。
此外還有其它特殊 keyword gatewaybroadcast 等,以及算術運算。較複雜的過濾表示用邏輯 and (&&)、or (||)、not (!)、以及「( )」來組合基本表示式。

範例

Ethernet 信頭
  • ether dst|src|host ehost:Ethernet 目的或來源位址是 ehostehost 可以是來自 /etc/ethers 的名稱或十六進位數字表示的 MAC 位址 (會忽略中間參雜的「:」、「.」、和「-」)。
  • ether ehost:錯誤。
  • [ether] broadcast:Ethernet 廣播封包。ether 可省略。
  • [ether] multicast:Ethernet 群播封包。ether 可省略。相當於 ether[0] & 1 != 0
  • [ether protoprotocol:Ethernet 的 Ether Type 是 protocolprotocol 可以是數字或名稱 ipip6arprarpatalkaarpdecnetscalatmopdlmoprcisostpipx、或 netbeui。註:由於這些名稱也是保留字,所以需要 backslash (\) 跳脫。
  • vlan [vlan_id]:
  • pppoed
  • pppoes [session_id]:
  • wlan ra|ta|addr1|addr2|addr3|addr4 ehost
  • [type wlan_type] [subtyp wlan_subtype]:
  • dir dir:
IP 位址或主機名稱
  • [ip|arp|rarp|ipv6] [dst|src] host hosthost 是 IPv4/IPv6 位址或主機名稱。前面可加協定限制、方向限制。ip host host 相當於 ether proto \ip and host host
  • gateway host:使用 host 作為 gateway 的封包,也就是使用 host 的 Ethernet 位址,但不是 host 的 IP 位址。host 的 IP 位址和 MAC 位址需要查得到。相當於 ether host ehost and not host host。
  • [dst|src] net net [mask netmask]:
  • [dst|src] net net[/len]:
  • ip broadcast
  • [ip|ip6] multicast
  • [[ip|ip6] proto] tcp|udp|icmp:協定是 tcp、ucp、或 icmp 封包。註:tcp, udp, and icmp 也是 keyword,所以需要 backslash (\) 跳脫。註:不能 chase the protocol header chain。
  • [ip|ip6] proto protocol:IPv4 或 IPv6 protocol type 是 protocol。protocol 可以是數字或名稱 icmp6, igmp, igrp, pim, ah, esp, or vrrp。註:不能 chase the protocol header chain.
  • [ip|ip6] protochain protocol:IPv4 或 IPv6 protocol chain 中含有 protocol。產生的 BPF 程式碼較複雜,且 kernel 不支援。
  • [tcp|udp] [dst|srcport port
  • [tcp|udp] [dst|srcportrange port1-port2
算術
  • expr relop exprrelop 是比大小 ><>=<==!= 之一。expr 可能是某個值、封包長度 len、或封包資料和正整數的 +-*/&|<<>>%^ 運算。(註:Linux 3.7 以後在 kernel 才能算 %^。) 封包資料用 proto[expr[:size]] 表示,指特定 proto 協定的 expr byte offset 的 size byte。size 可以是 1、2、4,預設是 1。特定 offset 或欄位可以用名稱表示,例如 tcp[tcpflags]。特定值可以用名稱表示,例如 tcp-syntcp-fin 等。
  • less|greater length:封包長度。相當於 len <= length 和 len >= length
其它

這些過濾描述會先編譯成 BPF 虛擬機器的指令碼,才給 BPF 執行。

參考來源

  1. Manpage of PCAP-FILTER
延伸閱讀
  • 顯示過濾式

2019年1月16日 星期三

pcapsipdump

pcapsipdump 基於 libpcap,將網路界面或 pcap 檔的封包以每個 SIP session (包括 RTP 或 T38 media) 儲存成不同的檔案。封包除了用 BPF 先行過濾外,可以用正規表示式過濾出需要的電話號碼或 SIP Method。另外,在每個 session 開始或結束時可以指定執行 shell 指令。

編譯

需要 libpcap-dev、libbsd-dev 等。
git svn clone --stdlayout https://svn.code.sf.net/p/pcapsipdump/code pcapsipdump
cd pcapsipdump
make
sudo make install

指令格式

pcapsipdump [-fpU] [-i interface | -r file] [-d output_directory] [-P pid_file]
            [-v level] [-R filter] [-m filter] [-n filter] [-l filter]
            [-B size] [-T limit] [-t trigger:action:param] [expression]
參數
  • -f:不 fork,也就是不成為 daemon
  • -p
  • -U
  • -i interface 或 -r file:必須指定網路界面或檔案
  • -d:指定輸出目錄和檔名,不然預設是 ... 
    • %f %t %i
  • -P:
  • -v:
  • -R:
  • -m filter:Method 過濾,預設是「^(INVITE|OPTIONS|REGISTER)$」。
  • -n:電話號碼過濾 (正規表示式)
  • -l:
  • -B:
  • -T:
  • -t:
  • expression:BPF 過濾表示式

使用範例

pcapsipdump ; 顯示使用說明
pcapsipdump -f -r test.pcapng -m '^INVIT$' -d ./%Y%m%d-%H%M%S-%f-%t.pcap

程式

main() @pcapsipdump.cpp
  1. 取得參數,剩下的部份是額外的 BPF 表示式。
  2. ...
  3. 使用 pcap_create() 或 pcap_open_offline() 取得網路界面或 pcap 檔的 pcap_t handle。
  4. 用 pcap_compile() 和 pcap_setfilter() 編譯和設定 BPF 過濾。預設過濾式「udp or vlan」,指令參數之外剩餘的部份就是 BPF 表示式。
  5. pcap_datalink() 查看 datalink 類型,換算出 IP 信頭位置。
  6. 可以 fork() 為 daemon。
  7. pcap_next_ex() 處理每個封包
    1. 每封包時間 15 秒檢查是否 session 過長應該結束
    2. fragment 封包:看是否需要儲存,然後處理下個封包。
    3. 如果是要儲存的 RTP 封包,儲存然後處理下個封包。
    4. 如果是 SIP 封包的話
      1. 檢查號碼是否符合儲存然後處理下個封包。
      2. 新 callid:檢查 Method 符合後產生輸出檔名。
      3. BYE
      4. 解析 SDP
      5. 是否有 fragment
    5. 其它封包:可開顯示
  8. 結束所有 session
  9. 結束 pcap_t
  10. 等候子行程
讀取封包需要取得 pcap_t
  • 從網路界面:pcap_create() → 設定選項 → pcap_activate()。pcap_findalldevs() 列出界面,然後 pcap_freealldevs() 釋出。pcap_lookupdev() 取得第一個非「loopback」的界面。
  • 從檔案:pcap_open_offline() 或 pcap_fopen_offline()。
  • 「假」的:pcap_open_dead()
  • 讀取封包:pcap_dispatch(), pacp_loop(), pcap_next(), pcap_next_ex()。
  • 結束取得封包:pcap_close()
過濾:pcap_compile() ...
寫 pcap 檔:pcap_dump_open() -> pcap_dump() -> pcap_dump_close()。
送出封包:pcap_inject()、pcap_sendpacket()

參考

2019年1月15日 星期二

primitive

primitive 是原始的、遠古的、早期的意思,含有不是從其它東西衍生出來的意思,也隱含有簡陋的、未分化的意思。
原始人叫 primitive man

primitive 也可以當名詞,就是原始人的意思,用在計算機科學的函數是指基本的原始函數,可翻作「原函數」、「原始函數」、「基元函數」

參考

Firefox 網頁轉成 PDF 檔的擴充

PDF Mage:支援本地檔案 (如 .md) 產生的網頁,可正確產生含有超連接的 PDF 檔。可設定頁寬 (Web page width) 1024px 以下或 Firefox 視窗不要開太大,避免字太小。

其它大多不支援本地檔案產生的網頁 (如 Save as PDFWeb to PDFPDF CreatorPrint Friendly & PDF) 或只跟內建的 Print 一樣沒有超連接 (如 Print to PDFWebsite to PDF)。

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...