کتابخانه‌ی استاندارد · شبکه

سانسورشکن net.censor

ابزارهایی برای شبکه‌هایی که در ترافیک دخالت می‌کنند: شناسایی پروتکل و خواندن نام سرور TLS، تکه‌تکه کردن ClientHello، لایه‌گذاری، مجموعه‌های قاعده‌ی دامنه با فهرست‌های ایران، نگهبان کاوش و حافظه‌ی تکرار.

واردسازی شبکه.سانسورشکن

نام آرگومان‌ها شناسه‌ی خود کد است و معادل فارسی ندارد؛ گونه‌ها، کلیدواژه‌ها و نام بسته‌ها با معادل فارسی نوشته می‌شوند.

بعضی شبکه‌ها فقط ترافیک را نمی‌برند، نگاهش هم می‌کنند: بایت‌های نخست یک اتصال به فیلتر می‌گویند چه پروتکلی است و نام سرور در نخستین پیام TLS می‌گوید به کدام سایت می‌روید. این بسته مجموعه‌ای از ابزارهای کوچک و مستقل از هم برای کار با همین چیزهاست. تشخیص پروتکل و تجزیه پیام آغازین آنچه فیلتر می‌خواند را می‌خوانند. تکه‌تکه کردن پیام آغازین و اندازه تکه‌ها از روی نام سرور آن پیام نخست را تکه‌تکه می‌کنند تا فیلتری که فقط یک بسته را نگاه می‌کند هرگز کل نام را نبیند. مجموعه دامنه و دسته‌بند از روی قاعده تصمیم می‌گیرند کدام میزبان‌ها مستقیم بروند، از پراکسی بروند یا هیچ‌جا نروند. نگهبان کاوش، حافظه تکرار و پاسخ طعمه تکه‌های کارسازی هستند که خودش را به کسی که امتحانش می‌کند لو نمی‌دهد. برای دیدن اینکه تکه‌ها در یک برنامه چگونه کنار هم می‌نشینند، ساختن برنامه‌ای به سبک v2ray یا VPN را بخوانید.

هیچ اتصالی باز نمی‌کند و وضعیت خودش را ندارد. روی بایت‌ها و متنی کار می‌کند که می‌دهید، پس جلوی هر کدام از بسته‌های پراکسی جا می‌شود: تونل، ساکس، پراکسی اچ‌تی‌تی‌پی، تروجان. هیچ‌کدامشان خودشان آن را صدا نمی‌زنند؛ هر جا لازم دارید خودتان وصلش کنید.

ایده‌های اصلی:

  • تشخیص پروتکل فقط چند بایت نخست لازم دارد و می‌گوید نوع تی ال اس، نوع اچ تی تی پی، نوع اس اس اچ، نوع ساکس۵ یا نوع ساکس۴، یا وقتی هنوز نمی‌تواند تشخیص دهد نوع داده ناکافی.
  • تجزیه پیام آغازین یک ClientHello از TLS را بدون کتابخانه‌ی TLS می‌خواند: نام سرور، پروتکل‌های پیشنهادی، و اینکه Encrypted Client Hello هست یا نه.
  • تکه‌تکه کردن یک نقشه به‌علاوه‌ی یک برش است. اندازه تکه‌ها یا اندازه تکه‌ها از روی نام سرور نقشه را می‌کشند (اندازه‌هایی که جمعشان برابر کل است)، برش بایت‌ها را به تکه‌های ساده می‌برد و تکه‌تکه کردن رکوردها یک رکورد TLS را به چند رکورد. تکه‌تکه کردن پیام آغازین کل کار را برای یک ClientHello انجام می‌دهد.
  • لایه‌گذاری اندازه‌ها را پنهان می‌کند: پوشاندن رکورد و پوشاندن جریان لایه‌ی تصادفی درون رکوردهایی اضافه می‌کنند که شبیه داده‌ی برنامه‌ی TLS هستند و گشودن رکورد آن را برمی‌دارد.
  • یک مجموعه دامنه قاعده‌های دامنه نگه می‌دارد (example.com، full:name، keyword:word)؛ یک دسته‌بند سه‌تایش و یک پیش‌فرض دارد و تصمیم پراکسی، تصمیم مستقیم یا تصمیم مسدود پاسخ می‌دهد.

چیزهایی که آدم را گیر می‌اندازد:

  • تکه‌تکه کردن رمزنگاری نیست و جادو هم نیست. در برابر فیلترهایی کمک می‌کند که فقط نخستین بسته یا نخستین رکورد را نگاه می‌کنند. فیلترها عوض می‌شوند و بسیاری از شبکه‌ها دوباره سر هم می‌کنند. روی همان شبکه‌ای که واقعا استفاده می‌کنید آزمایشش کنید و تنهایی به آن تکیه نکنید.
  • لایه‌گذاری هم رمزنگاری نیست. پوشاندن جریان اندازه‌ی تکه‌ها را پنهان می‌کند، نه آنچه درونشان است. آن را درون TLS یا کانال رمزشده‌ی دیگر به کار ببرید، هرگز به جای آن. رکوردهای لایه‌دار سرآیندهایی شبیه TLS دارند که ساخته‌ی همین بسته است: برای ناظر دقیق TLS واقعی به حساب نمی‌آیند.
  • پیش از خروج TLS تکه کنید، فقط در آغاز. برش روی نخستین رکورد یک دست‌دهی می‌رود. اتصالی که از پیش در جریان است اثری نمی‌بیند.
  • فهرست‌های ایران نقطه‌ی شروع‌اند. فهرست مستقیم ایران و فهرست فیلترشده فهرست‌های کوتاه و دست‌نوشته‌ای هستند که کهنه می‌شوند. آن‌ها را مثال‌هایی برای ویرایش بدانید و فهرست خودتان را در یک پرونده برای افزودن قاعده‌ها نگه دارید.
  • نگهبان کاوش و حافظه تکرار قفل ندارند. داده‌ی ساده‌اند. وقتی چند نخ از یکی استفاده می‌کنند فراخوانی‌ها را در قفل خودتان بپیچید. خودشان جلوی کاوش را نمی‌گیرند: از مسیر پذیرش کارسازتان صدایشان می‌زنید.
  • باید جایگزین شود فقط یک مقایسه است. کارسازی که وب‌سایت واقعی برای نشان دادن دارد همان است که پنهان می‌کند؛ بسته‌ی تروجان را ببینید.
  • تصادفی بودن امن است. عدد تصادفی و بایت‌های تصادفی از منبع امن سیستم می‌گیرند. تقسیم تصادفی تنها استثناست: با دانه عمدا تکرارپذیر است، که برای آزمون خوب است و برای پنهان کردن الگو انتخاب بدی.

تکه‌تکه کردن پیام آغازین TLS

کارخواه نخستین پیام TLS خود را به شکل یک رکورد می‌فرستد. اندازه تکه‌ها از روی نام سرور نام سرور را در آن پیدا می‌کند و برشی در میانه‌ی نام برنامه‌ریزی می‌کند؛ برش بایت‌ها را می‌برد و تکه‌ها یکی پس از دیگری، هر کدام در بسته‌ی خودشان، فرستاده می‌شوند. کارساز آن‌ها را به شکل یک جریان می‌خواند و همان پیام را می‌بیند. نمونه یک ClientHello را در دو تکه روی loopback می‌فرستد و نشان می‌دهد سمت گیرنده چه می‌خواند.

net-censor-guide-fragment.salam
// زبان: فارسی
واردسازی شبکه.سانسورشکن
واردسازی شبکه.تی سی پی
واردسازی همگام سازی

پایا HELLO := "160301008c010000880303000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f206465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283000613011302c02b0100003900000014001200000f7777772e6578616d706c652e636f6d000a00040002001d0010000e000c02683208687474702f312e31002b0003020304"

ناپایا port := 0
ناپایا seen := ""
ناپایا ready := همگام سازی.گروه انتظار جدید()

تابع server():
    srv := تی سی پی.پیوند(0)
    port = تی سی پی.درگاه(srv)
    همگام سازی.اتمام(ready)
    c := تی سی پی.پذیرش(srv)
    تی سی پی.تنظیم مهلت خواندن(c، 1500)
    تا درست:
        data := تی سی پی.خواندن(c، 4096)
        اگر data.طول() برابر 0:
            بشکن
        پایان
        seen += data.طول() + " "
    پایان
    تی سی پی.بستن(c)
پایان

تابع ریشه:
    همگام سازی.افزودن(ready، 1 برگردان صحیح۶۴)
    t := نخ‌ساز(server)
    همگام سازی.انتظار(ready)

    hello := سانسورشکن.از هگز(HELLO)
    sizes := سانسورشکن.اندازه تکه‌ها از روی نام سرور(hello.داده، hello.طول، نادرست)
    ناپایا pieces := سانسورشکن.برش(hello.داده، hello.طول، sizes)
    سرچاپ "نام سرور از بایت"، سانسورشکن.تجزیه پیام آغازین(hello.داده، hello.طول).جایگاه نام سرور، "شروع می‌شود و پس از"، sizes.بگیر(0)، "بایت بریده می‌شود"

    conn := تی سی پی.شماره گیری("127.0.0.1"، port)
    تی سی پی.غیرفعال‌سازی نگل(conn، درست)
    تکرار pieces.طول() در i:
        piece := pieces.بگیر(i)
        تی سی پی.نوشتن بایت(conn، piece.داده، piece.طول)
        همگام سازی.خواب میلی ثانیه(60)
    پایان
    تی سی پی.بستن(conn)
    نخ‌پیوند(t)
    سرچاپ "سرور خواند:"، seen
    سرچاپ "تکه‌های فرستاده‌شده:"، pieces.طول()
    سانسورشکن.آزاد کردن تکه‌ها(pieces)
پایان
خروجینام سرور از بایت 97 شروع می‌شود و پس از 104 بایت بریده می‌شود سرور خواند: 3 8 تکه‌های فرستاده‌شده: 2

این بایت‌های جریان را می‌برد که هر کارساز TCP دوباره سر هم می‌کند. تکه‌تکه کردن پیام آغازین کار دیگری می‌کند: رکورد را به چند رکورد TLS می‌برد، پس حتی فیلتری که بسته‌ها را سر هم می‌کند نام سرور را میان رکوردها شکسته می‌بیند. کارسازی که TLS را دنبال کند هر دو را می‌پذیرد. تکه‌ها را با مکثی کوتاه یا با گزینه‌ی TCP no-delay بفرستید تا هر کدام در بسته‌ی خودش برود.

قاعده‌های دامنه و فهرست‌های ایران

یک مجموعه دامنه قاعده‌ها را از متن می‌خواند، یکی در هر سطر: example.com با همان دامنه و هر چه زیرش است می‌خواند، full:name فقط همان نام، keyword:word هر میزبانِ شامل آن واژه. یک دسته‌بند یک مجموعه‌ی مسدود، یک مجموعه‌ی پراکسی و یک مجموعه‌ی مستقیم دارد و به ترتیب ثابت پاسخ می‌دهد: مسدود، سپس پراکسی، سپس مستقیم (مجموعه‌ی مستقیم یا هر نشانی خصوصی)، سپس پیش‌فرضش. پس قاعده‌ای در مجموعه‌ی پراکسی بر مجموعه‌ی مستقیم برتری دارد و نشانی خصوصی مستقیم است مگر اینکه چیز دیگری بگویید.

ناپایا classifier := سانسورشکن.دسته‌بند جدید(سانسورشکن.تصمیم پراکسی)
classifier.مستقیم = سانسورشکن.مجموعه مستقیم ایران()
سرچاپ سانسورشکن.دسته‌بندی(classifier، "www.digikala.com")   // مستقیم
سرچاپ سانسورشکن.دسته‌بندی(classifier، "mail.sharif.ir")     // مستقیم
سرچاپ سانسورشکن.دسته‌بندی(classifier، "youtube.com")        // پراکسی (پیش‌فرض)

فهرست مستقیم ایران دامنه‌های .ir و چند سایت بزرگ داخلی را دارد؛ فهرست فیلترشده سایت‌هایی که معمولا فیلترند. هر دو کوتاه‌اند و کهنه می‌شوند: آن‌ها را در یک پرونده کپی کنید، ویرایش کنید و مال خودتان را با افزودن قاعده‌ها بار کنید. برای مسیریابی که با برچسب کار می‌کند، تونل تونل.مسیریاب ایران و تونل.تجزیه قاعده‌ها را دارد.

پنهان کردن کارساز از کاوش

کارسازی که کاوش می‌شود اتصال‌هایی می‌بیند که احراز هویت نمی‌شوند. پاسخ امن این است که مثل یک وب‌سرور معمولی دیده شود: اتصال را به یک سایت واقعی بسپارید (باید جایگزین شود برای هر چه احراز نشده باشد بله می‌گوید)، یا دست‌کم یک ۴۰۴ ساده بفرستید (پاسخ طعمه). نگهبان کاوش حافظه اضافه می‌کند: پس از بیشینه شکست شکست از یک نشانی در بازه شمارش، اجازه نگهبان به مدت مدت مسدودی نه می‌گوید. حافظه تکرار بایت‌های نخست احراز هویت‌ها را به یاد می‌سپارد تا دست‌دهی ضبط‌شده‌ای که دوباره فرستاده شود دیده شود (تکراری است). یک انتظار تصادفی کوچک (تاخیر تصادفی) پیش از پاسخ به کارخواه ناموفق نمی‌گذارد زمان مسیر شکست آن را لو بدهد.

اگر وارونه سانسورشکن.اجازه نگهبان(guard، client_ip، now):
    close(connection)
وگرنه اگر وارونه authenticated:
    سانسورشکن.ثبت شکست(guard، client_ip، now)
    hand_to_real_website(connection)
پایان

کارساز تروجان کارخواه‌های ناموفق را از پیش به یک وب‌سایت واقعی می‌سپارد. این ابزارها لایه‌ی اضافه برای کارسازهایی هستند که خودتان می‌سازید.

چه باید دانست

  • هر تابع روی بایت‌ها و متنی که می‌دهید کار می‌کند. هیچ چیز اینجا سوکتی باز نمی‌کند یا وضعیت سراسری نگه نمی‌دارد.
  • تکه‌تکه کردن و لایه‌گذاری تدبیرهای جزئی‌اند، نه رمزنگاری؛ درون کانال رمزشده به کار ببرید و روی شبکه‌ی خودتان آزمایششان کنید.
  • فهرست‌های ایران کوتاه‌اند و زود کهنه می‌شوند. مال خودتان را نگه دارید.
  • نگهبان کاوش و حافظه تکرار داده‌ی ساده‌ی بدون قفل‌اند و باید آزاد شوند (آزاد کردن نگهبان، آزاد کردن حافظه تکرار)؛ مجموعه‌ها، تکه‌ها و بافرهایی که می‌سازید هم (آزاد کردن مجموعه دامنه، آزاد کردن تکه‌ها).
  • نشانی‌ها متن IPv4 یا متن IPv6 هستند؛ ابزارها نام را حل نمی‌کنند.
  • هیچ گزارشی خودکار نوشته نمی‌شود.

گونه‌ها

مجموعه دامنه DomainSet

ساختار مجموعه دامنه
مجموعه‌ای از قاعده‌های دامنه: دامنه‌های کامل (با همه‌ی زیردامنه‌هایشان)، نام‌های دقیق و کلیدواژه‌ها. با مجموعه دامنه جدید ساخته و با افزودن قاعده یا افزودن قاعده‌ها پر می‌شود.
نامانگلیسیگونهتوضیح
پسوندهاsuffixesنگاشت<رشته، منطقی>دامنه‌هایی که با خودشان و هر چه زیرشان است می‌خوانند.
دامنه‌های کاملfullsنگاشت<رشته، منطقی>نام‌هایی که باید دقیقا بخوانند.
کلیدواژه‌هاkeywordsوکتور<رشته>واژه‌هایی که با هر میزبانِ شامل آن‌ها می‌خوانند.
شمارcountصحیح = 0چند قاعده اضافه شده است.
net-censor-Domains.salam
// زبان: فارسی
واردسازی شبکه.سانسورشکن

تابع ریشه:
    ناپایا set := سانسورشکن.مجموعه دامنه جدید()
    سرچاپ سانسورشکن.افزودن قاعده(set، "example.com")، سانسورشکن.افزودن قاعده(set، "full:only.test.org")، سانسورشکن.افزودن قاعده(set، "keyword:torrent")
    سرچاپ سانسورشکن.افزودن قاعده(set، "domain:*.cdn.net")، سانسورشکن.افزودن قاعده(set، "regexp:a.*")، سانسورشکن.افزودن قاعده(set، "  ")
    سرچاپ سانسورشکن.افزودن قاعده‌ها(set، "# a comment\nblocked.io # trailing\n\nfoo.bar\n")، set.شمار
    سرچاپ سانسورشکن.تطبیق دامنه(set، "example.com")، سانسورشکن.تطبیق دامنه(set، "WWW.Example.COM.")، سانسورشکن.تطبیق دامنه(set، "badexample.com")
    سرچاپ سانسورشکن.تطبیق دامنه(set، "only.test.org")، سانسورشکن.تطبیق دامنه(set، "x.only.test.org")، سانسورشکن.تطبیق دامنه(set، "my-torrent-site.xyz")
    سرچاپ سانسورشکن.تطبیق دامنه(set، "a.b.cdn.net")، سانسورشکن.تطبیق دامنه(set، "x.blocked.io")، سانسورشکن.تطبیق دامنه(set، "net")
    سرچاپ set.پسوندها.اندازه()، set.دامنه‌های کامل.اندازه()، set.کلیدواژه‌ها.طول()
    سانسورشکن.آزاد کردن مجموعه دامنه(set)

    سرچاپ سانسورشکن.میزبان خصوصی("192.168.1.5")، سانسورشکن.میزبان خصوصی("172.20.0.1")، سانسورشکن.میزبان خصوصی("172.40.0.1")، سانسورشکن.میزبان خصوصی("localhost")، سانسورشکن.میزبان خصوصی("::1")، سانسورشکن.میزبان خصوصی("example.com")

    ناپایا classifier := سانسورشکن.دسته‌بند جدید(سانسورشکن.تصمیم پراکسی)
    classifier.مستقیم = سانسورشکن.مجموعه مستقیم ایران()
    classifier.مسدود = سانسورشکن.مجموعه دامنه جدید()
    سانسورشکن.افزودن قاعده(classifier.مسدود، "ads.example.org")
    هر host در ["www.digikala.com"، "mail.sharif.ir"، "youtube.com"، "ads.example.org"، "192.168.1.5"، "172.40.0.1"]:
        سرچاپ host، سانسورشکن.دسته‌بندی(classifier، host)
    پایان
    سرچاپ سانسورشکن.تصمیم پراکسی، سانسورشکن.تصمیم مستقیم، سانسورشکن.تصمیم مسدود

    filtered := سانسورشکن.مجموعه فیلترشده()
    سرچاپ سانسورشکن.تطبیق دامنه(filtered، "m.youtube.com")، سانسورشکن.تطبیق دامنه(filtered، "digikala.com")
    سرچاپ سانسورشکن.فهرست مستقیم ایران().شروع با("#")، سانسورشکن.فهرست فیلترشده().دربردارد("youtube.com")
پایان
خروجیtrue true true true false false 2 6 true true false true false true true true false 4 1 1 true true false true true false www.digikala.com 1 mail.sharif.ir 1 youtube.com 0 ads.example.org 2 192.168.1.5 1 172.40.0.1 0 0 1 2 true false true true

دسته‌بند Classifier

ساختار دسته‌بند
سه مجموعه‌ی دامنه و یک پیش‌فرض: دسته‌بندی به ترتیب از آن‌ها می‌پرسد و یک تصمیم برمی‌گرداند. با دسته‌بند جدید ساخته می‌شود و مجموعه‌ها را پر کنید.
نامانگلیسیگونهتوضیح
مسدودblockمجموعه دامنهمیزبان‌هایی که باید رد شوند. نخست بررسی می‌شود.
مستقیمdirectمجموعه دامنهمیزبان‌هایی که باید مستقیم به آن‌ها رسید.
پراکسیproxyمجموعه دامنهمیزبان‌هایی که باید از پراکسی بروند. دوم بررسی می‌شود، پس بر مستقیم و بر نشانی‌های خصوصی برتری دارد.
تصمیم پیش‌فرضdefault_decisionصحیح = 0با میزبانی که هیچ‌چیز با آن نخواند چه کنیم.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

پیام آغازین کارخواه ClientHello

ساختار پیام آغازین کارخواه
آنچه تجزیه پیام آغازین از نخستین پیام TLS که یک کارخواه می‌فرستد می‌خواند: نام سرور، پروتکل‌های پیشنهادی و چند واقعیت درباره‌اش.
نامانگلیسیگونهتوضیح
معتبرokمنطقی = نادرستدرست وقتی بایت‌ها یک ClientHello معتبرند (احتمالا بریده، ناقص را ببینید).
ناقصtruncatedمنطقی = نادرستدرست وقتی بایت‌ها پیش از پایان کل پیام تمام شدند. فیلدهای خوانده‌شده تا اینجا همچنان پر می‌شوند.
نسخه رکوردrecord_versionصحیح = 0شماره‌ی نسخه در سرآیند رکورد TLS.
نسخه پیامhello_versionصحیح = 0شماره‌ی نسخه در خود ClientHello.
طول رکوردrecord_lenصحیح = 0طولی که سرآیند رکورد اعلام می‌کند.
نام سرورsniرشته = ""نام سرور از افزونه‌ی Server Name Indication، با حروف کوچک، یا خالی اگر نباشد.
جایگاه نام سرورsni_offsetصحیح = -1نام سرور از کجای بایت‌ها شروع می‌شود، یا ۱-. فیلتر همین‌جا را نگاه می‌کند و اندازه تکه‌ها از روی نام سرور همین‌جا می‌برد.
طول نام سرورsni_lenصحیح = 0طول نام سرور.
پروتکل‌های برنامهalpnوکتور<رشته>پروتکل‌های برنامه‌ای که کارخواه پیشنهاد می‌کند، مثل h2 و http/1.1.
شمار رمزهاcipher_countصحیح = 0چند مجموعه‌ی رمز پیشنهاد شده است.
شمار افزونه‌هاext_countصحیح = 0پیام چند افزونه دارد.
دارای تی ال اس سیزدهhas_tls13منطقی = نادرستدرست وقتی TLS 1.3 در افزونه‌ی نسخه‌های پشتیبانی‌شده پیشنهاد شده است.
دارای ای سی اچhas_echمنطقی = نادرستدرست وقتی پیام افزونه‌ی Encrypted Client Hello دارد که نام واقعی سرور را پنهان می‌کند.
طول شناسه نشستsession_id_lenصحیح = 0طول شناسه‌ی نشستی که کارخواه فرستاد. کارخواه‌های TLS 1.3 ۳۲ بایت از آن می‌فرستند.
net-censor-Sniff.salam
// زبان: فارسی
واردسازی شبکه.سانسورشکن

پایا HELLO := "160301008c010000880303000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f206465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283000613011302c02b0100003900000014001200000f7777772e6578616d706c652e636f6d000a00040002001d0010000e000c02683208687474702f312e31002b0003020304"

تابع ریشه:
    hello := سانسورشکن.از هگز(HELLO)
    سرچاپ "hello bytes:"، hello.طول، سانسورشکن.به هگز(hello).طول()
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل(hello.داده، hello.طول))
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل("GET / HTTP/1.1" برگردان تهی*، 14))
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل("SSH-2.0-OpenSSH_9.6" برگردان تهی*، 19))
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل(سانسورشکن.از هگز("050100").داده، 3))
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل(سانسورشکن.از هگز("0401005000000001").داده، 8))
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل("GE" برگردان تهی*، 2))
    سرچاپ سانسورشکن.نام نوع(سانسورشکن.تشخیص پروتکل("zzzz" برگردان تهی*، 4))
    سرچاپ سانسورشکن.تشخیص پروتکل(hello.داده، hello.طول) برابر سانسورشکن.نوع تی ال اس، سانسورشکن.نوع ناشناخته، سانسورشکن.نوع اچ تی تی پی، سانسورشکن.نوع اس اس اچ، سانسورشکن.نوع ساکس۵، سانسورشکن.نوع ساکس۴، سانسورشکن.نوع داده ناکافی

    ch := سانسورشکن.تجزیه پیام آغازین(hello.داده، hello.طول)
    سرچاپ ch.معتبر، ch.ناقص، ch.طول رکورد
    سرچاپ ch.نام سرور، ch.جایگاه نام سرور، ch.طول نام سرور
    سرچاپ ch.نسخه رکورد، ch.نسخه پیام، ch.طول شناسه نشست، ch.شمار رمزها، ch.شمار افزونه‌ها
    سرچاپ ch.دارای تی ال اس سیزده، ch.دارای ای سی اچ، ch.پروتکل‌های برنامه.طول()، ch.پروتکل‌های برنامه.بگیر(0)، ch.پروتکل‌های برنامه.بگیر(1)
    سرچاپ سانسورشکن.استخراج نام سرور(hello.داده، hello.طول)

    cut := سانسورشکن.تجزیه پیام آغازین(hello.داده، 60)
    سرچاپ "cut short:"، cut.معتبر، cut.ناقص، cut.نام سرور.طول()
    سرچاپ "not tls:"، سانسورشکن.تجزیه پیام آغازین("GET / HTTP/1.1" برگردان تهی*، 14).معتبر
پایان
خروجیhello bytes: 145 290 tls http ssh socks5 socks4 short unknown true 0 2 3 4 5 6 true false 145 www.example.com 97 15 769 771 32 3 4 true false 2 h2 http/1.1 www.example.com cut short: false true 0 not tls: false

نگهبان کاوش ProbeGuard

ساختار نگهبان کاوش
تعداد احراز هویت‌های ناموفق را برای هر نشانی IP می‌شمارد و نشانی‌ای را که زیاد شکست بخورد مسدود می‌کند. با نگهبان کاوش جدید ساخته می‌شود. داده‌ی ساده است و قفل ندارد، پس فقط زیر قفل خودتان بین نخ‌ها شریکش کنید.
نامانگلیسیگونهتوضیح
بیشینه شکستmax_failsصحیح = 5چند شکست در بازه باعث مسدودی می‌شود.
بازه شمارشwindow_msصحیح۶۴ = 60000طول بازه‌ی شمارش، به میلی‌ثانیه.
مدت مسدودیban_msصحیح۶۴ = 600000مسدودی چند میلی‌ثانیه می‌ماند.
شکست‌هاfailsنگاشت<رشته، صحیح>شمار شکست هر نشانی.
آغاز بازهfirst_msنگاشت<رشته، صحیح۶۴>بازه‌ی جاری هر نشانی کی شروع شد.
زمان رفع مسدودیbanned_untilنگاشت<رشته، صحیح۶۴>هر نشانی مسدودشده تا کی مسدود است.
net-censor-Probe.salam
// زبان: فارسی
واردسازی شبکه.سانسورشکن

تابع ریشه:
    ناپایا guard := سانسورشکن.نگهبان کاوش جدید(3، 1000 برگردان صحیح۶۴، 5000 برگردان صحیح۶۴)
    سرچاپ guard.بیشینه شکست، guard.بازه شمارش، guard.مدت مسدودی
    سرچاپ سانسورشکن.اجازه نگهبان(guard، "1.2.3.4"، 0 برگردان صحیح۶۴)
    سرچاپ سانسورشکن.ثبت شکست(guard، "1.2.3.4"، 100 برگردان صحیح۶۴)، سانسورشکن.ثبت شکست(guard، "1.2.3.4"، 200 برگردان صحیح۶۴)، سانسورشکن.ثبت شکست(guard، "1.2.3.4"، 300 برگردان صحیح۶۴)
    سرچاپ سانسورشکن.اجازه نگهبان(guard، "1.2.3.4"، 400 برگردان صحیح۶۴)، سانسورشکن.اجازه نگهبان(guard، "5.6.7.8"، 400 برگردان صحیح۶۴)، سانسورشکن.اجازه نگهبان(guard، "1.2.3.4"، 5400 برگردان صحیح۶۴)
    سرچاپ سانسورشکن.ثبت شکست(guard، "9.9.9.9"، 0 برگردان صحیح۶۴)، سانسورشکن.ثبت شکست(guard، "9.9.9.9"، 2000 برگردان صحیح۶۴)، سانسورشکن.ثبت شکست(guard، "9.9.9.9"، 2100 برگردان صحیح۶۴)
    سانسورشکن.ثبت شکست(guard، "7.7.7.7"، 0 برگردان صحیح۶۴)
    سانسورشکن.ثبت شکست(guard، "7.7.7.7"، 10 برگردان صحیح۶۴)
    سانسورشکن.ثبت موفقیت(guard، "7.7.7.7")
    سرچاپ سانسورشکن.ثبت شکست(guard، "7.7.7.7"، 20 برگردان صحیح۶۴)، guard.شکست‌ها.بگیر("7.7.7.7")
    سانسورشکن.آزاد کردن نگهبان(guard)

    ناپایا cache := سانسورشکن.حافظه تکرار جدید(1000 برگردان صحیح۶۴، 4)
    سرچاپ cache.ماندگاری، cache.بیشینه ورودی
    سرچاپ سانسورشکن.تکراری است(cache، "a"، 0 برگردان صحیح۶۴)، سانسورشکن.تکراری است(cache، "a"، 500 برگردان صحیح۶۴)، سانسورشکن.تکراری است(cache، "a"، 1600 برگردان صحیح۶۴)
    سرچاپ cache.دیده‌شده.اندازه()
    سانسورشکن.آزاد کردن حافظه تکرار(cache)

    سرچاپ سانسورشکن.باید جایگزین شود(نادرست)، سانسورشکن.باید جایگزین شود(درست)
    wait := سانسورشکن.تاخیر تصادفی(5، 20)
    سرچاپ wait بزرگتربرابر 5، wait کوچکتربرابر 20
    سرچاپ سانسورشکن.پاسخ طعمه().زیررشته(0، 22)
    سرچاپ سانسورشکن.پاسخ طعمه().دربردارد("nginx")
پایان
خروجی3 1000 5000 true false false true false true true false false false false 1 1000 4 false true false 1 true false true true HTTP/1.1 404 Not Found true

حافظه تکرار ReplayCache

ساختار حافظه تکرار
کلیدهای اخیر (مثلا بایت‌های نخست احراز هویت) را به یاد می‌سپارد تا بگوید کی یکی بار دوم می‌آید. با حافظه تکرار جدید ساخته می‌شود. داده‌ی ساده است و قفل ندارد.
نامانگلیسیگونهتوضیح
ماندگاریttl_msصحیح۶۴ = 120000یک کلید چند میلی‌ثانیه به یاد می‌ماند. پیش‌فرض ۱۲۰۰۰۰.
بیشینه ورودیmax_entriesصحیح = 4096اندازه‌ای که در آن کلیدهای منقضی پاک می‌شوند. پیش‌فرض ۴۰۹۶.
دیده‌شدهseenنگاشت<رشته، صحیح۶۴>کلیدها و زمانی که هر یک آخرین بار دیده شد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

پایاها و متغیرها

تصمیم‌ها Decision…

آنچه دسته‌بندی برمی‌گرداند.
نامانگلیسیمقدار
تصمیم پراکسیDecisionProxy0
تصمیم مستقیمDecisionDirect1
تصمیم مسدودDecisionBlock2

نوع‌های پروتکل Kind…

آنچه تشخیص پروتکل برمی‌گرداند.
نامانگلیسیمقدار
نوع ناشناختهKindUnknown0
نوع تی ال اسKindTLS1
نوع اچ تی تی پیKindHTTP2
نوع اس اس اچKindSSH3
نوع ساکس۵KindSOCKS54
نوع ساکس۴KindSOCKS45
نوع داده ناکافیKindTooShort6

سیاست‌های تقسیم Split…

سیاست‌های اندازه تکه‌ها.
نامانگلیسیمقدار
تقسیم مساویSplitEven0
تقسیم تصادفیSplitRandom1
تقسیم پس از نخستین تکهSplitFirst2

بیشینه داده رکورد MaxRecordPayload

پایا بیشینه داده رکورد: صحیح۳۲ = 16000
بیشترین داده‌ای که پوشاندن جریان در یک رکورد می‌گذارد: ۱۶۰۰۰ بایت.
net-censor-Fragment.salam
// زبان: فارسی
واردسازی فشرده سازی
واردسازی شبکه.سانسورشکن

پایا HELLO := "160301008c010000880303000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f206465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283000613011302c02b0100003900000014001200000f7777772e6578616d706c652e636f6d000a00040002001d0010000e000c02683208687474702f312e31002b0003020304"

تابع total(v: وکتور<صحیح>): صحیح:
    ناپایا sum := 0
    تکرار v.طول() در i:
        sum += v.بگیر(i)
    پایان
    برگشت sum
پایان

تابع ریشه:
    hello := سانسورشکن.از هگز(HELLO)

    even := سانسورشکن.اندازه تکه‌ها(100، سانسورشکن.تقسیم مساوی، 3، 0، 1 برگردان صحیح۶۴)
    سرچاپ even.بگیر(0)، even.بگیر(1)، even.بگیر(2)، total(even)
    random := سانسورشکن.اندازه تکه‌ها(1000، سانسورشکن.تقسیم تصادفی، 5، 0، 42 برگردان صحیح۶۴)
    again := سانسورشکن.اندازه تکه‌ها(1000، سانسورشکن.تقسیم تصادفی، 5، 0، 42 برگردان صحیح۶۴)
    سرچاپ random.طول()، total(random)، random.بگیر(0) برابر again.بگیر(0)، random.بگیر(4) برابر again.بگیر(4)
    first := سانسورشکن.اندازه تکه‌ها(517، سانسورشکن.تقسیم پس از نخستین تکه، 2، 5، 0 برگردان صحیح۶۴)
    سرچاپ first.بگیر(0)، first.بگیر(1)
    سرچاپ سانسورشکن.اندازه تکه‌ها(3، سانسورشکن.تقسیم مساوی، 10، 0، 0 برگردان صحیح۶۴).طول()

    cuts := سانسورشکن.اندازه تکه‌ها از روی نام سرور(hello.داده، hello.طول، نادرست)
    سرچاپ cuts.بگیر(0)، cuts.بگیر(1)، total(cuts)
    lone := سانسورشکن.اندازه تکه‌ها از روی نام سرور(hello.داده، hello.طول، درست)
    سرچاپ lone.طول()، lone.بگیر(0)، lone.بگیر(1)، total(lone)

    ناپایا pieces := سانسورشکن.برش(hello.داده، hello.طول، cuts)
    سرچاپ pieces.طول()، فشرده سازی.برابری بافر(سانسورشکن.پیوست(pieces)، hello)
    سانسورشکن.آزاد کردن تکه‌ها(pieces)

    ناپایا records := سانسورشکن.تکه‌تکه کردن پیام آغازین(hello.داده، hello.طول، 4، سانسورشکن.تقسیم مساوی، 0 برگردان صحیح۶۴)
    سرچاپ records.طول()
    head := records.بگیر(0)
    سرچاپ head.طول، فشرده سازی.دریافت بایت(head، 0)، فشرده سازی.دریافت بایت(head، 1)، فشرده سازی.دریافت بایت(head، 2)
    all := سانسورشکن.پیوست(records)
    سرچاپ all.طول، all.طول برابر hello.طول + 15
    سرچاپ سانسورشکن.تجزیه پیام آغازین(all.داده، all.طول).معتبر، سانسورشکن.تجزیه پیام آغازین(head.داده، head.طول).ناقص
    سانسورشکن.آزاد کردن تکه‌ها(records)

    ناپایا by_hand := سانسورشکن.تکه‌تکه کردن رکوردها(hello.داده، hello.طول، cuts)
    سرچاپ by_hand.طول()، by_hand.بگیر(0).طول، by_hand.بگیر(1).طول
    سانسورشکن.آزاد کردن تکه‌ها(by_hand)
    سرچاپ "not a handshake:"، سانسورشکن.تکه‌تکه کردن پیام آغازین("GET / HTTP/1.1" برگردان تهی*، 14، 3، سانسورشکن.تقسیم مساوی، 0 برگردان صحیح۶۴).طول()
    سرچاپ سانسورشکن.بیشینه داده رکورد
پایان
خروجی34 33 33 100 5 1000 true true 5 512 3 104 41 145 3 1 103 145 2 true 4 40 22 3 1 160 true false false 2 109 41 not a handshake: 0 16000

تابع‌ها

مجموعه دامنه جدید NewDomainSet

تابع مجموعه دامنه جدید(): مجموعه دامنه
مجموعه‌ی خالی برمی‌گرداند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

افزودن قاعده AddRule

تابع افزودن قاعده(s &: مجموعه دامنه، rule: رشته): منطقی
یک قاعده اضافه می‌کند: example.com یا domain:example.com (آن دامنه و همه‌ی زیرش)، full:name (دقیقا همان نام) یا keyword:word. *. در ابتدا مجاز است. برای سطر خالی یا نوعی که پشتیبانی نمی‌شود، مثل regexp:، نادرست.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

افزودن قاعده‌ها AddRules

تابع افزودن قاعده‌ها(s &: مجموعه دامنه، text: رشته): صحیح
چند قاعده را از متن اضافه می‌کند، یک قاعده در هر سطر. سطرهای خالی و توضیح‌های #، حتی پس از یک قاعده، رد می‌شوند. برمی‌گرداند چند قاعده اضافه شد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

تطبیق دامنه MatchDomain

تابع تطبیق دامنه(s: مجموعه دامنه، host: رشته): منطقی
درست وقتی یک میزبان با مجموعه بخواند. بزرگی و کوچکی حروف و نقطه‌ی پایانی نادیده گرفته می‌شود و badexample.com با قاعده‌ی example.com نمی‌خواند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

آزاد کردن مجموعه دامنه FreeDomainSet

تابع آزاد کردن مجموعه دامنه(s &: مجموعه دامنه)
یک مجموعه را آزاد می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

میزبان خصوصی IsPrivateHost

تابع میزبان خصوصی(host: رشته): منطقی
درست برای localhost و نشانی‌های خصوصی، loopback و پیوند محلی: 127/8، 10/8، 172.16/12، 192.168/16، 169.254/16، ::1 و بازه‌های خصوصی و پیوند محلی IPv6.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

دسته‌بند جدید NewClassifier

تابع دسته‌بند جدید(default_decision: صحیح): دسته‌بند
دسته‌بندی با مجموعه‌های خالی و تصمیم پیش‌فرض داده‌شده برمی‌گرداند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

دسته‌بندی Classify

تابع دسته‌بندی(c: دسته‌بند، host: رشته): صحیح
برای یک میزبان تصمیم می‌گیرد: نخست مسدود، سپس پراکسی، سپس مستقیم (مجموعه‌ی مستقیم یا هر نشانی خصوصی)، و آخر پیش‌فرض.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

فهرست مستقیم ایران IranDirectList

تابع فهرست مستقیم ایران(): رشته
فهرست کوتاهی، به شکل متن قاعده، از سایت‌های داخلی که بدون پراکسی بهتر کار می‌کنند: .ir و چند سرویس شناخته‌شده. نقطه‌ی شروع است و باید ویرایش شود.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

فهرست فیلترشده FilteredList

تابع فهرست فیلترشده(): رشته
فهرست کوتاهی، به شکل متن قاعده، از سایت‌هایی که معمولا در ایران فیلتر هستند. فقط نقطه‌ی شروع: کهنه می‌شود و کامل نیست، پس پیش از تکیه بر آن بررسی‌اش کنید.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

مجموعه مستقیم ایران IranDirectSet

تابع مجموعه مستقیم ایران(): مجموعه دامنه
فهرست مستقیم ایران که در یک مجموعه دامنه بار شده است.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

مجموعه فیلترشده FilteredSet

تابع مجموعه فیلترشده(): مجموعه دامنه
فهرست فیلترشده که در یک مجموعه دامنه بار شده است.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Domains.salam

تشخیص پروتکل Sniff

تابع تشخیص پروتکل(p: تهی*، n: صحیح): صحیح
به نخستین بایت‌های یک اتصال نگاه می‌کند و می‌گوید با کدام پروتکل شروع می‌شوند: یکی از مقدارهای Kind. فقط چند بایت لازم دارد و وقتی کافی نیستند نوع داده ناکافی می‌گوید.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Sniff.salam

نام نوع KindName

تابع نام نوع(k: صحیح): رشته
نام کوتاهی برای یک مقدار Kind برمی‌گرداند: tls، http، ssh، socks5، socks4، short یا unknown.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Sniff.salam

تجزیه پیام آغازین ParseClientHello

تابع تجزیه پیام آغازین(p: تهی*، n: صحیح): پیام آغازین کارخواه
یک ClientHello از TLS را از حافظه و بدون هیچ کتابخانه‌ی TLS تجزیه می‌کند. بایت‌های بریده نتیجه‌ی جزئی با ناقص می‌دهند؛ هر چه ClientHello نباشد معتبر را نادرست می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Sniff.salam

استخراج نام سرور ExtractSNI

تابع استخراج نام سرور(p: تهی*، n: صحیح): رشته
فقط نام سرور یک ClientHello را برمی‌گرداند، یا متن خالی.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Sniff.salam

از هگز FromHex

تابع از هگز(text: رشته): فشرده سازی.بافر بایت
متن هگز را به یک بافر بایت تبدیل می‌کند. فاصله و شکست سطر نادیده گرفته می‌شود.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Sniff.salam

به هگز ToHex

تابع به هگز(b: فشرده سازی.بافر بایت): رشته
بایت‌های یک بافر را به شکل هگز با حروف کوچک برمی‌گرداند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Sniff.salam

عدد تصادفی RandomInt

تابع عدد تصادفی(lo: صحیح، hi: صحیح): صحیح
یک عدد تصادفی از lo تا hi، هر دو شامل، از منبع تصادفی امن سیستم برمی‌گرداند.
net-censor-Padding.salam
// زبان: فارسی
واردسازی فشرده سازی
واردسازی شبکه.سانسورشکن

تابع ریشه:
    body := "secret payload"
    wrapped := سانسورشکن.پوشاندن رکورد(body برگردان تهی*، body.طول()، 20)
    سرچاپ wrapped.طول، فشرده سازی.دریافت بایت(wrapped، 0)، فشرده سازی.دریافت بایت(wrapped، 1)، فشرده سازی.دریافت بایت(wrapped، 2)
    ناپایا got := فشرده سازی.بافر بایت جدید()
    سرچاپ سانسورشکن.گشودن رکورد(wrapped.داده، wrapped.طول، got)، got.طول
    سرچاپ "needs more:"، سانسورشکن.گشودن رکورد(wrapped.داده، wrapped.طول - 1، got)
    سرچاپ "not a record:"، سانسورشکن.گشودن رکورد("GET / HTTP/1.1" برگردان تهی*، 14، got)
    سرچاپ "too big:"، سانسورشکن.پوشاندن رکورد(body برگردان تهی*، 20000، 0).طول

    ناپایا big := فشرده سازی.بافر بایت جدید()
    تکرار 40000 در i:
        فشرده سازی.افزودن بایت(big، i % 251)
    پایان
    stream := سانسورشکن.پوشاندن جریان(big.داده، big.طول، 5، 50)
    ناپایا back := فشرده سازی.بافر بایت جدید()
    ناپایا offset := 0
    ناپایا records := 0
    تا offset کوچکتر stream.طول:
        used := سانسورشکن.گشودن رکورد(((stream.داده برگردان صحیح۶۴) + (offset برگردان صحیح۶۴)) برگردان تهی*، stream.طول - offset، back)
        اگر used کوچکتربرابر 0:
            بشکن
        پایان
        offset += used
        records++
    پایان
    سرچاپ records، فشرده سازی.برابری بافر(back، big)، offset برابر stream.طول

    سرچاپ سانسورشکن.طول لایه(100، 10، 10، 64)
    سرچاپ سانسورشکن.طول لایه(100، 0، 0، 1)
    سرچاپ سانسورشکن.بایت‌های تصادفی(32).طول، سانسورشکن.عدد تصادفی(5، 5)
    r := سانسورشکن.عدد تصادفی(10، 20)
    سرچاپ r بزرگتربرابر 10، r کوچکتربرابر 20
پایان
خروجی43 23 3 3 43 14 needs more: 0 not a record: -1 too big: 0 3 true true 28 0 32 5 true true

بایت‌های تصادفی RandomBytes

تابع بایت‌های تصادفی(n: صحیح): فشرده سازی.بافر بایت
بافری از بایت‌های تصادفی از منبع تصادفی امن برمی‌گرداند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Padding.salam

طول لایه PadLength

تابع طول لایه(payload_len: صحیح، min_pad: صحیح، max_pad: صحیح، block: صحیح): صحیح
طول لایه‌ی تصادفی را بین یک کمینه و یک بیشینه برمی‌گزیند و اگر اندازه‌ی بلوک بزرگ‌تر از ۱ داده شود، مجموع را تا مضربی از آن گرد می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Padding.salam

پوشاندن رکورد WrapRecord

تابع پوشاندن رکورد(p: تهی*، n: صحیح، pad: صحیح): فشرده سازی.بافر بایت
چند بایت را در رکوردی می‌پیچد که شبیه داده‌ی برنامه‌ی TLS است (نوع ۲۳، نسخه ۳.۳) و پس از آن‌ها لایه‌ی تصادفی اضافه می‌کند. رکورد یک سرآیند درونی ۴ بایتی با طول واقعی و طول لایه دارد. اگر از ۱۶۳۸۴ بایت بیشتر شود خالی.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Padding.salam

گشودن رکورد UnwrapRecord

تابع گشودن رکورد(p: تهی*، n: صحیح، payload &: فشرده سازی.بافر بایت): صحیح
یک رکورد ساخته‌ی پوشاندن رکورد را می‌خواند: بایت‌های واقعی‌اش را در یک بافر می‌گذارد و برمی‌گرداند رکورد چند بایت گرفت، ۰ وقتی بایت بیشتری لازم است و ۱- وقتی رکورد معتبر نیست.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Padding.salam

پوشاندن جریان WrapStream

تابع پوشاندن جریان(p: تهی*، n: صحیح، min_pad: صحیح، max_pad: صحیح): فشرده سازی.بافر بایت
یک جریان کامل بایت را در رکوردهای پوشاندن رکورد تا بیشینه داده رکورد بایت می‌پیچد که هر یک لایه‌ی تصادفی بین دو حد دارد. اندازه‌ها را پنهان می‌کند، نه محتوا را: رمزنگاری نیست.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Padding.salam

اندازه تکه‌ها SplitSizes

تابع اندازه تکه‌ها(total: صحیح، policy: صحیح، pieces: صحیح، param: صحیح، seed: صحیح۶۴): وکتور<صحیح>
نقشه می‌کشد یک طول کل را چگونه تکه‌تکه کنیم: اندازه‌ها را برمی‌گرداند. سیاست تقسیم مساوی، تقسیم تصادفی یا تقسیم پس از نخستین تکه است؛ pieces شمار تکه‌ها، param اندازه‌ی تکه‌ی نخست برای تقسیم پس از نخستین تکه و seed سیاست تصادفی را تکرارپذیر می‌کند. اندازه‌ها همیشه جمعشان برابر کل است.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

اندازه تکه‌ها از روی نام سرور SNISplitSizes

تابع اندازه تکه‌ها از روی نام سرور(p: تهی*، n: صحیح، head_first: منطقی): وکتور<صحیح>
برشی را در میانه‌ی نام سرور یک ClientHello برنامه‌ریزی می‌کند تا هیچ تکه‌ای کل نام را نداشته باشد. با head_first بایت نخست تنها می‌رود. بدون نام سرور خواندنی به دو تکه‌ی هم‌اندازه برمی‌گردد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

برش Slice

تابع برش(p: تهی*، n: صحیح، sizes: وکتور<صحیح>): وکتور<فشرده سازی.بافر بایت>
حافظه را به تکه‌هایی با اندازه‌های داده‌شده می‌برد (آخرین تکه باقی را می‌گیرد) و آن‌ها را به شکل بافر برمی‌گرداند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

تکه‌تکه کردن رکوردها FragmentRecords

تابع تکه‌تکه کردن رکوردها(p: تهی*، n: صحیح، sizes: وکتور<صحیح>): وکتور<فشرده سازی.بافر بایت>
یک رکورد TLS را به چند رکورد با اندازه‌های بار داده‌شده می‌برد که هر یک سرآیند خودش را دارد، پس گیرنده همان پیام را در چند رکورد می‌بیند. نوع و نسخه‌اش حفظ می‌شود.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

تکه‌تکه کردن پیام آغازین FragmentClientHello

تابع تکه‌تکه کردن پیام آغازین(p: تهی*، n: صحیح، pieces: صحیح، policy: صحیح، seed: صحیح۶۴): وکتور<فشرده سازی.بافر بایت>
نخستین پیام TLS یک اتصال را با یک سیاست و دانه به شمار داده‌شده رکورد می‌شکند. نتیجه، اگر به ترتیب فرستاده شود، همچنان برای سرور یک ClientHello معتبر است، با ۵ بایت سرآیند اضافه برای هر رکورد اضافه. اگر بایت‌ها رکورد دست‌دهی نباشند خالی.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

پیوست Concat

تابع پیوست(pieces: وکتور<فشرده سازی.بافر بایت>): فشرده سازی.بافر بایت
بافرها را به ترتیب به یکی می‌چسباند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

آزاد کردن تکه‌ها FreePieces

تابع آزاد کردن تکه‌ها(pieces &: وکتور<فشرده سازی.بافر بایت>)
یک بردار بافر و بافرهای درونش را آزاد می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Fragment.salam

نگهبان کاوش جدید NewProbeGuard

تابع نگهبان کاوش جدید(max_fails: صحیح، window_ms: صحیح۶۴، ban_ms: صحیح۶۴): نگهبان کاوش
یک نگهبان می‌سازد: چند شکست، در چه مدت، چه مدت مسدودی می‌دهد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

اجازه نگهبان GuardAllowed

تابع اجازه نگهبان(g: نگهبان کاوش، ip: رشته، now_ms: صحیح۶۴): منطقی
درست وقتی یک نشانی در زمان داده‌شده، به میلی‌ثانیه، مسدود نیست.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

ثبت شکست GuardRecordFail

تابع ثبت شکست(g &: نگهبان کاوش، ip: رشته، now_ms: صحیح۶۴): منطقی
یک تلاش ناموفق از یک نشانی را در یک زمان ثبت می‌کند. وقتی همین یکی باعث مسدودی شد درست برمی‌گرداند. شکست‌های قدیمی‌تر از بازه شمرده نمی‌شوند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

ثبت موفقیت GuardRecordOK

تابع ثبت موفقیت(g &: نگهبان کاوش، ip: رشته)
یک موفقیت از یک نشانی را ثبت می‌کند و شمار شکستش را پاک می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

آزاد کردن نگهبان FreeProbeGuard

تابع آزاد کردن نگهبان(g &: نگهبان کاوش)
یک نگهبان را آزاد می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

حافظه تکرار جدید NewReplayCache

تابع حافظه تکرار جدید(ttl_ms: صحیح۶۴، max_entries: صحیح): حافظه تکرار
حافظه‌ای می‌سازد با ماندگاری برای کلیدها و اندازه‌ای که در آن پاکسازی می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

تکراری است ReplaySeen

تابع تکراری است(c &: حافظه تکرار، key: رشته، now_ms: صحیح۶۴): منطقی
اگر کلید در ماندگاری‌اش دیده شده باشد درست برمی‌گرداند. وگرنه همین حالا کلید را به یاد می‌سپارد و نادرست برمی‌گرداند، پس دو بار پرسیدن از تکرار خبر می‌دهد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

آزاد کردن حافظه تکرار FreeReplayCache

تابع آزاد کردن حافظه تکرار(c &: حافظه تکرار)
یک حافظه را آزاد می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

باید جایگزین شود ShouldFallback

تابع باید جایگزین شود(authenticated: منطقی): منطقی
درست برای اتصالی که احراز هویت نشد: باید به جای رها شدن به سایت طعمه سپرده شود. تنها تصمیمی است که کارساز مقاوم در برابر کاوش می‌گیرد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

تاخیر تصادفی DelayMs

تابع تاخیر تصادفی(min_ms: صحیح، max_ms: صحیح): صحیح
یک تاخیر تصادفی بین دو حد، به میلی‌ثانیه، برمی‌گرداند. اندکی صبر پیش از پاسخ به کارخواه ناموفق نشان نمی‌دهد بررسی چقدر سریع بود.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam

پاسخ طعمه DecoyResponse

تابع پاسخ طعمه(): رشته
یک پاسخ HTTP آماده برمی‌گرداند که شبیه صفحه‌ی استاندارد 404 Not Found یک وب‌سرور رایج است، برای کارسازی که سایت واقعی برای نشان دادن ندارد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-censor-Probe.salam