PacketSender
PacketSender یک تولیدکننده packet لایه ۳ برای IPv4 است. این node هنگام startup، packetهای خام IPv4 را از پیش میسازد و در مدت تعیینشده آنها را روی worker packet lineهای WaterWall میفرستد.
کاربرد اصلی آن آزمایش کنترلشده مسیر packet است. در کنار PacketReceiver میتوان از آن برای پیدا کردن source IPهای قابل دسترس یا مجاز در محیطهای محدودشده بر اساس IP استفاده کرد: از بازههای پیشنهادی packet بسازید، آنها را از مسیر مورد نظر بفرستید و سپس گزارش گیرنده را بررسی کنید تا مشخص شود packetهای کدام source IP رسیدهاند.
این node را فقط روی شبکهها و بازههای آدرسی به کار ببرید که مجوز آزمایش آنها را دارید. نتیجه آزمایش source IP به شبکه سمت sender نیز وابسته است. اگر provider، مسیر kernel، backend مربوط به raw socket یا شبکه upstream آدرسهای source غیرمحلی را مسدود کند، ممکن است packetهای تولیدشده اصلاً از sender خارج نشوند.
جایگاه رایج
خروجی raw IPv4:
PacketSender -> RawSocket
همراه packet manipulation:
PacketSender -> IpManipulator -> RawSocket
packet transport شبیه WireGuard:
شاخهی منبع Packet: PacketSender -> Bridge A
شاخهی UDP/WireGuard: UdpStatelessSocket -> WireGuardDevice -> Bridge B
Bridge A و Bridge B را با هم جفت کنید. هر دو PacketSender و
UdpStatelessSocket فقط در ابتدای chain قرار میگیرند؛ بنابراین باید در
شاخههای جداگانه باشند.
سمت receiver متناظر:
RawSocket -> PacketReceiver
PacketSender یک adapter از نوع chain-head و singleton است. باید در ابتدای یک chain لایه ۳ قرار بگیرد و وجود next برای آن الزامی است.
چه کاری انجام میدهد
- یک بازه CIDR برای source IPv4 یا آرایهای از این بازهها را میپذیرد.
- یک آدرس IPv4 برای destination میپذیرد.
- برای
TCP،UDP،ICMPیاALLpacket خام IPv4 میسازد. - ارسال از هر source IP را به تعداد
packets-per-ipتکرار میکند. - پیش از آغاز ارسال، کل packet store را در حافظه میسازد.
- indexهای packet را میان workerها تقسیم میکند.
- با تعیین deadline برای هر packet، ارسالها را در طول
duration-msپخش میکند. - پیش از هر ارسال، routing context روی packet line را بهروزرسانی میکند.
- پس از پایان ارسال، worker packet lineها را نمیبندد و برایشان
Finishنمیفرستد. - اگر سمت downstream روی worker packet line مربوطه
Finishبفرستد، timer و حلقه ارسال آن worker را متوقف میکند.
بازههای source به همان ترتیبی که در config آمدهاند پردازش میشوند و ارسال آنها با هم interleave نمیشود.
تست source-IP Allowlist
PacketSender و PacketReceiver برای سناریوهایی مناسباند که دسترسی به مسیر یا سرویس بر اساس source IP محدود شده است. روال معمول چنین است:
PacketSenderرا با بازههای IP مبدأ مورد نظر درsource-ipv4-rangeتنظیم کنید.PacketReceiverرا با همان rangeها تنظیم کنید.- packetها را به سمت host یا packet chain گیرنده بفرستید.
- گزارش گیرنده را بخوانید.
- source IPهایی را که تحویل کامل یا نزدیک به کامل دارند بهعنوان گزینههای بهتر در نظر بگیرید.
در گیرنده، PacketReceiver.protocol-number را برابر protocolهای مورد انتظار و PacketReceiver.expected-packets-per-ip را در همه حالتها، از جمله ALL، برابر PacketSender.packets-per-ip بگذارید. گیرنده مجموع هر IP را خودش محاسبه میکند و protocolها را جداگانه گزارش میدهد. برای چند protocol میتوان از آرایههایی مانند [6, 17] یا ["TCP", "UDP"] استفاده کرد.
نمونه تنظیم
ICMP probing:
{
"name": "packet-sender",
"type": "PacketSender",
"settings": {
"source-ipv4-range": [
"198.51.100.0/24",
"203.0.113.0/24"
],
"dest-ipv4": "203.0.113.20",
"protocol-number": "ICMP",
"duration-ms": 5000,
"packets-per-ip": 100
},
"next": "raw-ip"
}
TCP-shaped probing:
{
"name": "packet-sender",
"type": "PacketSender",
"settings": {
"source-ipv4-range": "198.51.100.0/24",
"dest-ipv4": "203.0.113.20",
"protocol-number": "TCP",
"duration-ms": 5000,
"packets-per-ip": 10,
"dest-port": 443,
"src-port": "random"
},
"next": "raw-ip"
}
فیلدهای ضروری
فیلدهای سطح بالا:
| فیلد | نوع | توضیح |
|---|---|---|
name | string | نام دلخواه node. باید داخل فایل config یکتا باشد. |
type | string | باید دقیقاً "PacketSender" باشد. |
settings | object | لازم است و نباید خالی باشد. |
next | string | لازم است. node لایه ۳ بعدی packetهای تولیدشده را دریافت میکند. |
فیلدهای ضروری داخل settings:
| فیلد | نوع | توضیح |
|---|---|---|
source-ipv4-range | string یا آرایه string | یک CIDR range از نوع IPv4، یا آرایهای از CIDR rangeهای IPv4. |
dest-ipv4 | string | آدرس IPv4 مقصد. باید IPv4 تکی باشد، نه CIDR. |
protocol-number | string | یکی از TCP، UDP، ICMP یا ALL. به حروف کوچک و بزرگ حساس نیست. |
duration-ms | integer | مدت ارسال مثبت، بر حسب میلیثانیه. |
dest-port | integer | برای TCP، UDP و ALL لازم است. باید غیرصفر و در بازه 0..65535 باشد. |
src-port | integer یا "random" | برای TCP، UDP و ALL لازم است. باید غیرصفر یا "random" باشد. |
dest-port و src-port برای ICMP لازم نیستند.
تنظیمات اختیاری
| گزینه | نوع | پیشفرض | توضیح |
|---|---|---|---|
packets-per-ip | integer | 1 | تعداد تکرار ارسال از هر source IP؛ باید مثبت باشد. در حالت ALL، هر بار برای ۲۵۵ protocol مختلف packet فرستاده میشود. |
وقتی src-port برابر "random" باشد، پیادهسازی فعلی بر اساس source IP، destination IP و protocol یک port ثابت از بازه ephemeral یعنی 49152..65535 انتخاب میکند. این انتخاب برای شکل packet تولیدشده deterministic است و برای هر packet دوباره تصادفی نمیشود.
شکل packetهای تولیدشده
همه packetهای تولیدشده IPv4 هستند و این ویژگیها را دارند:
| فیلد | مقدار |
|---|---|
| TTL | 64 |
| fragment flag | Don't fragment (DF) |
| source IP | یک آدرس از source-ipv4-range |
| destination IP | dest-ipv4 |
| checksums | پیش از ساخته شدن packet store محاسبه میشوند |
شکلهای protocol-specific:
protocol-number | packet تولیدشده |
|---|---|
TCP | TCP segment حداقلی با flag ACK، sequence/ack numberهای deterministic، portهای تنظیمشده و checksum معتبر. |
UDP | UDP datagram حداقلی با portهای تنظیمشده و checksum معتبر. |
ICMP | ICMP echo request با identifier/sequence deterministic و checksum معتبر. |
ALL | برای هر source IP و هر تکرار، یک packet برای protocol numberهای 0 تا 254 میسازد. protocolهای 6، 17 و 1 بهترتیب شکل معتبر TCP، UDP و ICMP دارند؛ سایر موارد packetهای IPv4 با payload هشتبایتی opaque هستند. |
حالت ALL در هر تکرار برای 255 protocol مختلف packet تولید میکند، نه 256.
زمانبندی و workerها
پیش از شروع runtime، PacketSender همه packetها را در یک packet store پیوسته میسازد. هنگام startup:
- indexهای کل packetها میان workerها تقسیم میشوند
- هر worker از worker packet line پایدار خودش استفاده میکند
- هر packet بر اساس index و
duration-msیک deadline سراسری میگیرد - workerها packetهای آماده را میفرستند و اگر زمان packet بعدی هنوز نرسیده باشد، one-shot timer را دوباره فعال میکنند
به این ترتیب packetها در تمام مدت تعیینشده پخش میشوند و کل store یکباره بهصورت burst ارسال نمیشود. اگر موعد چند packet همزمان برسد، ممکن است یک worker آنها را پشت سر هم بفرستد.
محدودیتها
- تعداد کل source IPها باید داخل
uint32_tجا شود. - تعداد کل packetها باید داخل
uint64_tجا شود. - مجموع اندازهٔ packetهای ساختهشده در حافظه باید در
size_tجا شود. - اندازهٔ packet store در حافظه به
8 GiBمحدود است. required_padding_left = 0.
بازههای بزرگ، حالت ALL و مقدارهای زیاد packets-per-ip مصرف حافظه را سریع بالا میبرند. در صورت نیاز تست را با بازههای کوچکتر یا در چند اجرای جدا انجام دهید.
معناشناسی packet-line
PacketSender از worker packet lineهایی استفاده میکند که chain ساخته است. اینها lineهای کمکی و پایدار هر worker هستند، نه lineهای جداگانه برای هر connection.
PacketSender packet lineها را از بین نمیبرد و Finish را نشانه تکمیل موفق نمیداند. یک Finish از سمت downstream، timer و حلقه ارسال worker مربوطه را برای همیشه متوقف میکند؛ در حالت تکمیل عادی، فقط زمانی در log ثبت میشود که همه packetهای تخصیصیافته ارسال شده باشند.
نکتههای عملی
- در سمت مقصد از
PacketReceiverاستفاده کنید تا تعداد packetهای دریافتی از هر source IP را ببینید. - مقدار
report-after-msدرPacketReceiverرا بیشتر ازduration-msفرستنده بگذارید و برای تأخیر شبکه و جابهجایی احتمالی ترتیب packetها هم زمان در نظر بگیرید. - اگر شبکه اجازه میدهد، برای probe سادهٔ مسیر از
ICMPاستفاده کنید. - وقتی محیط محدودشده رفتار متفاوتی بر اساس protocol یا port دارد، از
TCP،UDPیاALLاستفاده کنید. - اگر شبکه سمت sender اعتبارسنجی source address انجام دهد، ممکن است بازههای source جعلی یا غیرمحلی پیش از رسیدن به peer WaterWall فیلتر شوند.
متادیتای node
متادیتای برگرفته از کد منبع:
| ویژگی | مقدار |
|---|---|
| node flags | kNodeFlagChainHead | kNodeFlagSingleton |
can_have_prev | false |
can_have_next | true |
layer_group | kNodeLayer3 |
layer_group_prev_node | kNodeLayerNone |
layer_group_next_node | kNodeLayer3 |
required_padding_left | 0 بایت |