پرش به مطلب اصلی

HalfDuplex

HalfDuplex یک قابلیت است که هر اتصال (Connection) را به دو اتصال تبدیل می‌کند:

  • یک اتصال فقط برای ارسال داده‌ها استفاده می‌شود.
  • اتصال دیگر فقط برای دریافت داده‌ها استفاده می‌شود.

در ابتدای برقراری هر کدام از این اتصالات، یک Handshake از نوع TLS انجام می‌شود، حتی اگر دامنه‌های متفاوتی داشته باشند.

مزایای HalfDuplex:

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

نکات:

  • اتصالات با انتقال دوطرفه داده، معمولاً نشان‌دهنده وجود تونل هستند.
    • مثلاً در HTTP/2 معمولی، ابتدا آپلود کم و سپس دانلود زیاد انجام می‌شود.
    • اما در VPN با Multiplexing، آپلود به طور مداوم روی اتصال انجام می‌شود.
  • این ویژگی برای تونل‌های معکوس (Reverse Tunnel) برای حفظ کیفیت سرویس ضروری است.
  • احتمالاً تونل‌های عادی port-to-port را نیز در برابر فیلتر شدن مقاوم می‌کند (هنوز تست نشده).

ویدیو های آموزشی

آموزش تانل زدن به روش waterwall بین سرور ایران و خارج: آموزش تانل v2ray

اجرای ساده چند پورت (Multi-port)

نحوه اعمال HalfDuplex در حالت چند پورت ساده، با فرض آدرس سرور خارج 1.1.1.1:

سرور ایران

{
"name": "simple_multiport_hd_client",
"nodes": [
{
"name": "input",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": [23, 65535],
"nodelay": true
},
"next": "port_header"
},
{
"name": "port_header",
"type": "HeaderClient",
"settings": {
"data": "src_context->port"
},
"next": "halfc"
},
{
"name": "halfc",
"type": "HalfDuplexClient",
"next": "output"
},
{
"name": "output",
"type": "TcpConnector",
"settings": {
"nodelay": true,
"address": "1.1.1.1",
"port": 443
}
}
]
}
سرور خارج
{
"name": "simple_multiport_hd_server",
"nodes": [
{
"name": "input",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": 443,
"nodelay": true
},
"next": "halfs"
},
{
"name": "halfs",
"type": "HalfDuplexServer",
"settings": {},
"next": "port_header"
},
{
"name": "port_header",
"type": "HeaderServer",
"settings": {
"override": "dest_context->port"
},
"next": "output"
},
{
"name": "output",
"type": "TcpConnector",
"settings": {
"nodelay": true,
"address": "127.0.0.1",
"port": "dest_context->port"
}
}
]
}

پیکربندی Reverse Reality با mux

پیکربندی Reverse Reality با استفاده از mux که توسط نویسنده برای کاربرانش استفاده می‌شود:

فرضیات
  • fake sni: sahab.ir
  • ip kharej: 2.2.2.2
  • password: passwd
سرور ایران
{
"name": "reverse_reality_grpc_client_hd_multiport_client",
"nodes": [
{
"name": "outbound_to_core",
"type": "TcpConnector",
"settings": {
"nodelay": true,
"address": "127.0.0.1",
"port": "dest_context->port"
}
},
{
"name": "header",
"type": "HeaderServer",
"settings": {
"override": "dest_context->port"
},
"next": "outbound_to_core"
},
{
"name": "bridge1",
"type": "Bridge",
"settings": {
"pair": "bridge2"
},
"next": "header"
},
{
"name": "bridge2",
"type": "Bridge",
"settings": {
"pair": "bridge1"
},
"next": "reverse_client"
},
{
"name": "reverse_client",
"type": "ReverseClient",
"settings": {
"minimum-unused": 16
},
"next": "pbclient"
},
{
"name": "pbclient",
"type": "ProtoBufClient",
"settings": {},
"next": "h2client"
},
{
"name": "h2client",
"type": "Http2Client",
"settings": {
"host": "sahab.ir",
"port": 443,
"path": "/",
"content-type": "application/grpc",
"concurrency": 64
},
"next": "halfc"
},
{
"name": "halfc",
"type": "HalfDuplexClient",
"next": "reality_client"
},
{
"name": "reality_client",
"type": "RealityClient",
"settings": {
"sni": "sahab.ir",
"password": "passwd"
},
"next": "outbound_to_iran"
},
{
"name": "outbound_to_iran",
"type": "TcpConnector",
"settings": {
"nodelay": true,
"address": "1.1.1.1",
"port": 443
}
}
]
}
فرضیات
  • fake sni: sahab.ir
  • ip kharej: 2.2.2.2
  • password: passwd
سرور خارج
{
"name": "reverse_reality_grpc_hd_multiport_server",
"nodes": [
{
"name": "users_inbound",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": [23, 65535],
"nodelay": true
},
"next": "header"
},
{
"name": "header",
"type": "HeaderClient",
"settings": {
"data": "src_context->port"
},
"next": "bridge2"
},
{
"name": "bridge2",
"type": "Bridge",
"settings": {
"pair": "bridge1"
}
},
{
"name": "bridge1",
"type": "Bridge",
"settings": {
"pair": "bridge2"
}
},
{
"name": "reverse_server",
"type": "ReverseServer",
"settings": {},
"next": "bridge1"
},
{
"name": "pbserver",
"type": "ProtoBufServer",
"settings": {},
"next": "reverse_server"
},
{
"name": "h2server",
"type": "Http2Server",
"settings": {},
"next": "pbserver"
},
{
"name": "halfs",
"type": "HalfDuplexServer",
"settings": {},
"next": "h2server"
},
{
"name": "reality_server",
"type": "RealityServer",
"settings": {
"destination": "reality_dest",
"password": "passwd"
},
"next": "halfs"
},
{
"name": "kharej_inbound",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": 443,
"nodelay": true,
"whitelist": ["2.2.2.2/32"]
},
"next": "reality_server"
},
{
"name": "reality_dest",
"type": "TcpConnector",
"settings": {
"nodelay": true,
"address": "sahab.ir",
"port": 443
}
}
]
}
نکته مهم بدون توجه به تعداد هسته‌های سرور، تعداد Worker ها در سرور خارج

را همیشه 4 برابر تعداد Worker های سرور ایران قرار دهید (حتی اگر 8 برابر). این کار سرعت را به میزان قابل توجهی بهبود می‌بخشد.

دلیل آن ارتباطی به مصرف CPU ندارد، بلکه هر Worker یک اتصال مجزا ایجاد می‌کند و کاربران روی یک اتصال Multiplexed قرار نمی‌گیرند.

توجه این نکته فقط برای Reverse Reality با mux صادق است. در سایر روش‌ها،

بهتر است تعداد Worker ها صفر باشد.