این آموزش به شما کمک میکند که یک اسکریپت برای مانیتورینگ لاگهای SIP بنویسید و آن را برای نیازهای خود سفارشی کنید. این اسکریپت با استفاده از tcpdump بستههای SIP را رهگیری میکند و اطلاعات مربوط به تماسها را استخراج میکند.
پروتکل SIP (Session Initiation Protocol) یکی از پرکاربردترین پروتکلها در شبکههای VoIP است که برای برقراری و مدیریت تماسهای صوتی و تصویری استفاده میشود. در این آموزش، یک اسکریپت پایتون مینویسیم که میتواند لاگهای SIP را تجزیه و تحلیل کند.
قبل از اجرای اسکریپت، مطمئن شوید که ابزار tcpdump روی سرور یا سیستم شما نصب شده است. در سیستمهای مبتنی بر Debian (مانند Ubuntu)، میتوانید با دستور زیر آن را نصب کنید:
sudo apt update && sudo apt install tcpdump -y
همچنین برای اجرای اسکریپت نیاز به Python 3 دارید. اگر هنوز پایتون روی سیستم شما نصب نیست، میتوانید از این دستور استفاده کنید:
sudo apt install python3 -y
کد اصلی شامل مراحل زیر است:
- اجرای tcpdump برای شنود بستههای SIP روی پورت 5060.
- خواندن خروجی tcpdump بهصورت real-time.
- استفاده از regex برای استخراج اطلاعات تماس.
- چاپ اطلاعات تماس استخراجشده در ترمینال.
import re
import subprocess
def capture_sip_logs():
# اجرای tcpdump برای شنود بستههای SIP روی پورت 5060
cmd = ["sudo", "tcpdump", "-i", "any", "-A", "-n", "port", "5060"]
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True)
flag = False
cid, did, ext, party = None, None, None, None
for line in process.stdout:
line = line.strip()
if "SIP/2.0 200 OK" in line:
flag = True
continue
if flag and "From:" in line:
match = re.search(r'From: "?([^"]*)"? <sip:([^@]+)@', line)
if match:
cid = match.group(1).strip() if match.group(1) else match.group(2).strip()
if flag and "To:" in line:
match = re.search(r'To:<sip:(\d+)@', line)
if match:
did = match.group(1).strip()
if flag and "Remote-Party-ID:" in line:
match = re.search(r'Remote-Party-ID: "?([^"]*)"? <sip:[^>]+>;party=(\w+)', line)
if match:
ext, party = match.groups()
ext = ext.strip()
party = party.strip()
result = f"as CID = {cid} and DID = {did} and EXT = {ext} is {party}"
print(result) # نمایش در Bash
flag = False
if __name__ == "__main__":
capture_sip_logs()
اجرای اسکریپت
برای اجرای اسکریپت، کافی است دستور زیر را در ترمینال اجرا کنید:
sudo python3 sip_logger.py
اگر نیاز به توقف اجرای اسکریپت دارید، میتوانید کلید Ctrl + C
را فشار دهید.
شما میتوانید این اسکریپت را برای نیازهای خاص خود تغییر دهید. در ادامه چند روش برای سفارشیسازی آورده شده است:
تغییر فیلتر پورت
اگر SIP شما روی پورتی غیر از 5060 اجرا میشود، مقدار پورت را در متغیر cmd
تغییر دهید:
cmd = ["sudo", "tcpdump", "-i", "any", "-A", "-n", "port", "5061"]
ذخیره دادهها در فایل
اگر میخواهید اطلاعات تماس را در یک فایل ذخیره کنید، میتوانید print(result)
را به کد زیر تغییر دهید:
with open("sip_logs.txt", "a") as log_file:
log_file.write(result + "\n")
.
چه اطلاعاتی از بستههای SIP میتوان استخراج کرد؟
پروتکل SIP شامل پیامهای متنی است که برای برقراری، مدیریت و پایان دادن به تماسهای VoIP استفاده میشود. با استفاده از tcpdump و Regex، میتوان اطلاعات مهمی از این پیامها استخراج کرد.
۱.۱. شماره تماسگیرنده (Caller ID یا CID)
- شمارهای که تماس را برقرار کرده است.
- در هدر From: قرار دارد.
- فرمت آن معمولاً اینگونه است:
From: "atari" <sip:1001@simotel.com>
- مقدار 1001 شماره تماسگیرنده است.
۱.۲. شماره مقصد (DID یا شماره مقصد)
- شمارهای که تماس به آن فرستاده شده است.
- در هدر To: قرار دارد.
- فرمت آن به این شکل است:
To: <sip:2001@simotal.com>
- مقدار 2001 شماره مقصد است.
۱.۳. داخلی (Extension یا EXT)
- اگر تماس به یک داخلی خاص هدایت شده باشد، این مقدار نشان میدهد که کدام داخلی مقصد تماس است.
- معمولاً در هدر Remote-Party-ID: قرار دارد.
- نمونهای از این هدر:
Remote-Party-ID: "Alice" <sip:3001@domain.com>;party=called
- مقدار 3001 نشاندهنده داخلی مقصد است.
۱.۴. وضعیت تماس (Call Status)
- میتوان فهمید که تماس موفق بوده یا رد شده است.
- در پیامهای SIP/2.0 200 OK یا SIP/2.0 486 Busy Here یا SIP/2.0 404 Not Found نمایش داده میشود.
- برخی از کدهای مهم SIP:
100 Trying
→ در حال پردازش180 Ringing
→ در حال زنگ خوردن200 OK
→ تماس برقرار شد403 Forbidden
→ دسترسی مسدود شده404 Not Found
→ شماره وجود ندارد486 Busy Here
→ مشغول است
۱.۵. نوع طرف تماس (Calling Party Type)
- نشان میدهد که تماسگیرنده چه نوع طرفی است.
- مقدار party در Remote-Party-ID: مشخص میکند که تماس از سمت Caller یا Callee است.
- نمونه:
Remote-Party-ID: "atari" <sip:3001@simotel.com>;party=called
- مقدار
party=called
نشان میدهد که این شماره تماس گیرنده (Caller) است. - مقدار
party=calling
یعنی این شماره تماسشونده (Callee) است.
۲.۱. آدرس IP و سرویسدهنده SIP
- میتوان آدرس IP سرور VoIP یا کلاینت SIP را پیدا کرد.
- نمونهای از لاگ:
Via: SIP/2.0/UDP 192.168.1.10:5060;branch=z9hG4bK1234abcd
- مقدار 192.168.1.10 آدرس IP سرور است.
۲.۲. نوع دیوایس یا نرمافزار SIP
- برخی از کلاینتهای SIP، نوع دیوایس یا نرمافزار مورد استفاده را ارسال میکنند.
- این اطلاعات در هدر User-Agent: قرار دارد.
- نمونه:
User-Agent: MicroSIP/3.19.32
- مقدار MicroSIP/3.19.32 نشان میدهد که کاربر از نرمافزار MicroSIP نسخه ۳.۱۹.۳۲ استفاده میکند.
۲.۳. آدرسهای RTP (برای صدا)
- تماسهای SIP معمولاً از پروتکل RTP برای ارسال صدا استفاده میکنند.
- آدرس RTP در هدر SDP قرار دارد:
c=IN IP4 192.168.1.20
m=audio 4000 RTP/AVP 0 8 101
- مقدار 192.168.1.20 آدرس IP ارسالکننده صدا است.
- مقدار 4000 شماره پورتی است که برای صدا استفاده میشود.
در این اسکریپت، میتوان اطلاعات مفیدی از تماسهای SIP دریافت کرد: شماره تماسگیرنده (CID)
شماره مقصد (DID)
داخلی مقصد (EXT)
وضعیت تماس (Call Status)
نوع طرف تماس (Caller/Callee)
آدرس IP سرور SIP
نوع نرمافزار SIP (User-Agent)
آدرس RTP برای صدا
اما اطلاعاتی مانند محتوای صوتی مکالمه، رمزهای عبور و موقعیت جغرافیایی دقیق کاربر قابل دریافت نیستند.
این اطلاعات میتواند برای تحلیل تماسها، عیبیابی مشکلات شبکه VoIP و بررسی امنیتی بسیار مفید باشد.
پیشنهادات برای توسعه بیشتر
- افزودن رابط گرافیکی: میتوان خروجی را در یک داشبورد وب نمایش داد.
- ارسال اطلاعات به یک API: میتوان دادهها را به یک سرور Django ارسال کرد.
- استفاده از WebSocket: برای نمایش زنده اطلاعات در مرورگر.
امیدوارم این آموزش برای شما مفید باشد!