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

پراکسی net/proxy

وصل شدن از راه پراکسی HTTP یا SOCKS5، تنها یا زنجیره‌ای.

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

پراکسی واسطه‌ای است که اتصال را از طرف برنامه برقرار می‌کند. این بسته تونل را می‌سازد و یک اتصال تی سی پی معمولی برمی‌گرداند که مثل اتصال مستقیم خوانده و نوشته می‌شود.

دو گونه پراکسی پشتیبانی می‌شود. پراکسی HTTP (پراکسی اچ‌تی‌تی‌پی جدید، اغلب روی درگاه ۳۱۲۸ یا ۸۰۸۰) تونل را با یک درخواست CONNECT باز می‌کند؛ پراکسی SOCKS5 (پراکسی ساکس۵ جدید، درگاه ۱۰۸۰، یا ۹۰۵۰ برای Tor) دست‌دهی دودویی کوچک خودش را دارد. هر دو "host:port" می‌گیرند و گونه‌های «با احراز هویت» نام کاربر و گذرواژه را هم می‌افزایند. شماره‌گیری یک اتصال تی سی پی برمی‌گرداند؛ اگر به پراکسی نرسیم یا پراکسی نپذیرد، اتصال خالی است، پس همیشه آن را با تی سی پی.اتصال معتبر بررسی کنید.

اشتباه‌های رایج

  • دست‌دهی مهلت ندارد. پراکسی‌ای که اتصال را بپذیرد ولی هرگز پاسخ ندهد، شماره‌گیری را تا ابد منتظر می‌گذارد و راهی برای گذاشتن مهلت پیش از دست‌دهی نیست. اگر این مهم است، شماره‌گیری را در نخی اجرا کنید که بتوانید از آن دست بکشید.
  • هیچ چیز از محیط خوانده نمی‌شود. HTTPS_PROXY، ALL_PROXY و NO_PROXY نادیده گرفته می‌شوند؛ خودتان آن‌ها را بخوانید، همان‌طور که راهنمای نخست می‌کند.
  • نشانی باید host:port با یک نام یا نشانی IPv4 باشد. متن در نخستین دونقطه شکسته می‌شود، پس نشانی IPv6 پراکسی مثل [::1]:1080 فهمیده نمی‌شود و نبودن درگاه آن را صفر می‌کند.
  • نام‌ها را پراکسی پیدا می‌کند. SOCKS5 مقصد را به شکل نام میزبان می‌فرستد، پس جستجوی DNS را پراکسی انجام می‌دهد. با Tor همین را می‌خواهید، ولی یعنی مقصد باید از شبکه‌ی پراکسی با نامش در دسترس باشد.
  • خروجی یک اتصال TCP ساده است. برای HTTPS آن را با تی سی پی.ارتقا به تی ال اس ارتقا دهید، همان‌طور که راهنمای HTTPS نشان می‌دهد؛ بسته خودش تا خود پراکسی TLS نمی‌زند.

خواندن تنظیمات پراکسی از یک نشانی

تنظیمات پراکسی معمولا به شکل یک نشانی می‌رسد، مثلا از متغیر محیطی HTTPS_PROXY یا پرونده‌ی پیکربندی: socks5://user:pass@host:1080. بسته بخش‌ها را جداجدا می‌گیرد، پس برنامه با چند سطر طرح، اعتبارنامه و نشانی را جدا می‌کند. طرح‌های ناشناخته را باید گزارش داد، نه این‌که بی‌صدا نادیده گرفت.

net-proxy-guide-url.salam
واردسازی شبکه.پراکسی
واردسازی رشته

تابع از نشانی(نشانی: رشته، خوب &: منطقی): پراکسی.پراکسی:
    خوب = درست
    ناپایا باقی := نشانی
    ناپایا ساکس := نادرست
    اگر رشته.شروع با(باقی، "socks5://"):
        ساکس = درست
        باقی = باقی.زیررشته(۹، باقی.طول() - ۹)
    وگرنه رشته.شروع با(باقی، "http://"):
        باقی = باقی.زیررشته(۷، باقی.طول() - ۷)
    وگرنه:
        خوب = نادرست
        برگشت پراکسی.پراکسی {}
    پایان
    ناپایا کاربر := ""
    ناپایا گذرواژه := ""
    جای اَت := باقی.بیاب("@")
    اگر جای اَت >= ۰:
        اعتبارنامه := باقی.زیررشته(۰، جای اَت)
        باقی = باقی.زیررشته(جای اَت + ۱، باقی.طول() - جای اَت - ۱)
        دونقطه := اعتبارنامه.بیاب(":")
        کاربر = اعتبارنامه.زیررشته(۰، دونقطه)
        گذرواژه = اعتبارنامه.زیررشته(دونقطه + ۱، اعتبارنامه.طول() - دونقطه - ۱)
    پایان
    اگر ساکس: برگشت پراکسی.پراکسی ساکس۵ با احراز هویت(باقی، کاربر، گذرواژه) پایان
    برگشت پراکسی.پراکسی اچ‌تی‌تی‌پی با احراز هویت(باقی، کاربر، گذرواژه)
پایان

تابع ریشه:
    نشانی‌ها := ["http://10.0.0.5:3128"، "socks5://127.0.0.1:9050"، "socks5://ali:[email protected]:1080"، "ftp://old.example.net:21"]
    هر ن در نشانی‌ها:
        ناپایا خوب := نادرست
        پ := از نشانی(ن، خوب)
        اگر وارونه خوب:
            سرچاپ ن، "-> پشتیبانی نمی‌شود"
            گذر
        پایان
        ناپایا نوع := "http"
        اگر پ.نوع == پراکسی.نوع ساکس۵: نوع = "socks5" پایان
        سرچاپ ن، "->"، نوع، پ.میزبان، پ.درگاه، "کاربر=[" + پ.نام کاربری + "]"
    پایان
پایان
خروجیhttp://10.0.0.5:3128 -> http 10.0.0.5 3128 کاربر=[] socks5://127.0.0.1:9050 -> socks5 127.0.0.1 9050 کاربر=[] socks5://ali:[email protected]:1080 -> socks5 gw.example.net 1080 کاربر=[ali] ftp://old.example.net:21 -> پشتیبانی نمی‌شود

تونل چه شکلی دارد

این برنامه بدون شبکه اجرا می‌شود: یک پراکسی HTTP ساختگی کوچک را روی یک درگاه آزاد محلی در یک نخ راه می‌اندازد، از راه آن شماره‌گیری می‌کند و درخواستی را که پراکسی گرفته چاپ می‌کند. همین درخواست کل پروتکل پراکسی HTTP است: سطر CONNECT host:port، سرآیند Host و اگر اعتبارنامه باشد سرآیند Proxy-Authorization: Basic که user:password را به شکل پایه۶۴ دارد. وقتی پراکسی 200 پاسخ داد، هر بایت بی‌تغییر رد می‌شود و برای همین پاسخ پژواک روی همان اتصال برمی‌گردد.

net-proxy-guide-local.salam
واردسازی شبکه.پراکسی
واردسازی شبکه.تی سی پی
واردسازی رشته

ناپایا شنونده := تی سی پی.سرور {}
ناپایا دیده‌شده := ""

تابع پراکسی ساختگی():
    ا := تی سی پی.پذیرش(شنونده)
    دیده‌شده = تی سی پی.خواندن(ا، ۴۰۹۶)
    تی سی پی.نوشتن(ا، "HTTP/1.1 200 Connection established\r\n\r\n")
    پیام := تی سی پی.خواندن(ا، ۱۰۰)
    تی سی پی.نوشتن(ا، "پژواک: " + پیام)
    تی سی پی.بستن(ا)
پایان

تابع ریشه:
    شنونده = تی سی پی.پیوند(۰)
    کارگر := نخ‌ساز(پراکسی ساختگی)
    پ := پراکسی.پراکسی اچ‌تی‌تی‌پی با احراز هویت("127.0.0.1:" + رشته.از عدد(تی سی پی.درگاه(شنونده) برگردان صحیح۶۴)، "ali"، "secret")
    اتصال := پراکسی.شماره‌گیری(پ، "example.com"، ۴۴۳)
    اگر وارونه تی سی پی.اتصال معتبر(اتصال):
        سرچاپ "پراکسی تونل را نپذیرفت"
        برگشت ۱
    پایان
    تی سی پی.نوشتن(اتصال، "سلام")
    سرچاپ تی سی پی.خواندن(اتصال، ۱۰۰)
    تی سی پی.بستن(اتصال)
    نخ‌پیوند(کارگر)
    چاپ رشته.جایگزینی(دیده‌شده، "\r\n"، "\n")
    تی سی پی.بستن سرور(شنونده)
    برگشت ۰
پایان
خروجیپژواک: سلام CONNECT example.com:443 HTTP/1.1 Host: example.com:443 Proxy-Authorization: Basic YWxpOnNlY3JldA== Proxy-Connection: Keep-Alive

احراز هویت Basic فقط پایه۶۴ است، نه رمزنگاری. روی شبکه‌ی نامطمئن، از پراکسی‌ای استفاده کنید که از راه VPN یا تونل SSH به آن می‌رسید، یا مثل بخش بعد فقط ترافیک TLS از آن رد کنید.

HTTPS از راه پراکسی

تونل هر بایتی را جابه‌جا می‌کند، از جمله TLS. پراکسی را برای درگاه ۴۴۳ میزبان واقعی شماره‌گیری کنید، سپس اتصال را با تی سی پی.ارتقا به تی ال اس و پیکربندی تی ال اس برای همان نام میزبان به TLS تبدیل کنید. پراکسی فقط نام میزبان و بایت‌های رمزشده را می‌بیند. برای آزمودن، یک پراکسی محلی مثل Squid راه بیندازید:

docker run -d -p 3128:3128 ubuntu/squid
net-proxy-guide-https.salam
واردسازی شبکه.پراکسی
واردسازی شبکه.تی سی پی
واردسازی تی ال اس
واردسازی رشته

تابع خط نخست(متن: رشته): رشته:
    جای شکست خط := متن.بیاب("\r\n")
    اگر جای شکست خط < ۰: برگشت متن پایان
    برگشت متن.زیررشته(۰، جای شکست خط)
پایان

تابع ریشه:
    میزبان := "example.com"
    پ := پراکسی.پراکسی اچ‌تی‌تی‌پی جدید("127.0.0.1:3128")
    اتصال := پراکسی.شماره‌گیری(پ، میزبان، ۴۴۳)
    اگر وارونه تی سی پی.اتصال معتبر(اتصال):
        سرچاپ "تونلی از " + پ.میزبان + ":" + رشته.از عدد(پ.درگاه برگردان صحیح۶۴) + " ساخته نشد"
        برگشت ۱
    پایان
    ناپایا امن := تی سی پی.ارتقا به تی ال اس(اتصال، تی ال اس.پیکربندی جدید(میزبان))
    اگر وارونه تی ال اس.اتصال معتبر(امن):
        سرچاپ "TLS شکست خورد: " + تی ال اس.خطای اتصال(امن)
        برگشت ۱
    پایان
    تی ال اس.نوشتن(امن، "GET / HTTP/1.1\r\nHost: " + میزبان + "\r\nConnection: close\r\n\r\n")
    سرچاپ خط نخست(تی ال اس.خواندن(امن، ۴۰۹۶))
    تی ال اس.بستن اتصال(امن)
    برگشت ۰
پایان

اگر پراکسی‌ای گوش نکند، برنامه پیام «تونلی از 127.0.0.1:3128 ساخته نشد» را چاپ می‌کند و با ۱ بیرون می‌رود.

زنجیره با بازگشت به اتصال مستقیم

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

net-proxy-guide-chain.salam
واردسازی شبکه.پراکسی
واردسازی شبکه.تی سی پی

تابع ریشه:
    ناپایا زنجیره := پراکسی.زنجیره جدید()
    پراکسی.افزودن(زنجیره، پراکسی.پراکسی ساکس۵ جدید("127.0.0.1:9050"))
    پراکسی.افزودن(زنجیره، پراکسی.پراکسی اچ‌تی‌تی‌پی با احراز هویت("exit.example.net:3128"، "team"، "s3cret"))

    ناپایا اتصال := پراکسی.شماره‌گیری زنجیره‌ای(زنجیره، "example.com"، ۸۰)
    اگر وارونه تی سی پی.اتصال معتبر(اتصال):
        سرچاپ "زنجیره کار نمی‌کند، اتصال مستقیم امتحان می‌شود"
        اتصال = تی سی پی.شماره گیری("example.com"، ۸۰)
    پایان
    اگر وارونه تی سی پی.اتصال معتبر(اتصال):
        سرچاپ "به example.com نمی‌رسیم"
        برگشت ۱
    پایان
    تی سی پی.نوشتن(اتصال، "HEAD / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
    پاسخ := تی سی پی.خواندن(اتصال، ۴۰۹۶)
    سرچاپ پاسخ.زیررشته(۰، پاسخ.بیاب("\r\n"))
    تی سی پی.بستن(اتصال)
    برگشت ۰
پایان

هر حلقه پیش از نخستین بایت داده‌ی واقعی یک رفت‌وبرگشت می‌افزاید، پس زنجیره‌ها را کوتاه نگه دارید. برای استفاده از Tor آن را محلی اجرا کنید (docker run -d -p 9050:9050 dperson/torproxy) و پراکسی ساکس۵ جدید("127.0.0.1:9050") را حلقه‌ی اول بگذارید.

گونه‌ها

پراکسی Proxy

ساختار پراکسی
یک پراکسی.
نامانگلیسیگونهتوضیح
نوعkindصحیح = 0نوع؛ یکی از ثابت‌های نوع.
میزبانhostرشته = ""میزبان.
درگاهportصحیح = 0درگاه.
نام کاربریusernameرشته = ""نام کاربری، اگر لازم باشد.
گذرواژهpasswordرشته = ""گذرواژه.
net-proxy-Proxy.salam
واردسازی شبکه.پراکسی

تابع ریشه:
    الف := پراکسی.پراکسی اچ‌تی‌تی‌پی جدید("10.0.0.1:3128")
    سرچاپ الف.نوع == پراکسی.نوع اچ‌تی‌تی‌پی، الف.میزبان، الف.درگاه
    ب := پراکسی.پراکسی اچ‌تی‌تی‌پی با احراز هویت("proxy.local:8080"، "ali"، "رمز")
    سرچاپ ب.نام کاربری، ب.گذرواژه
    ج := پراکسی.پراکسی ساکس۵ جدید("127.0.0.1:1080")
    د := پراکسی.پراکسی ساکس۵ با احراز هویت("socks.local:1080"، "u"، "p")
    سرچاپ ج.نوع == پراکسی.نوع ساکس۵، د.درگاه
    ناپایا ز := پراکسی.زنجیره جدید()
    پراکسی.افزودن(ز، ج)
    پراکسی.افزودن(ز، الف)
    سرچاپ ز.پراکسی‌ها.طول()
پایان
خروجیtrue 10.0.0.1 3128 ali رمز true 1080 2

زنجیره پراکسی Chain

ساختار زنجیره پراکسی
زنجیره‌ای از پراکسی‌ها که پشت‌سرهم استفاده می‌شوند.
نامانگلیسیگونهتوضیح
پراکسی‌هاitemsوکتور<پراکسی>پراکسی‌ها به ترتیب.

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

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

نوع اچ‌تی‌تی‌پی TypeHTTP

پایا نوع اچ‌تی‌تی‌پی: صحیح۳۲ = 0
پراکسی HTTP با روش CONNECT.

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

نوع ساکس۵ TypeSOCKS5

پایا نوع ساکس۵: صحیح۳۲ = 1
پراکسی SOCKS5.

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

تابع‌ها

پراکسی اچ‌تی‌تی‌پی جدید NewHTTPProxy

تابع پراکسی اچ‌تی‌تی‌پی جدید(addr: رشته): پراکسی
پراکسی HTTP از نشانی host:port؛ متن در نخستین دونقطه شکسته می‌شود، پس نشانی IPv6 کار نمی‌کند.

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

پراکسی اچ‌تی‌تی‌پی با احراز هویت NewHTTPProxyAuth

تابع پراکسی اچ‌تی‌تی‌پی با احراز هویت(addr: رشته، username: رشته، password: رشته): پراکسی
پراکسی HTTP با نام کاربری و گذرواژه.

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

پراکسی ساکس۵ جدید NewSOCKS5Proxy

تابع پراکسی ساکس۵ جدید(addr: رشته): پراکسی
پراکسی SOCKS5.

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

پراکسی ساکس۵ با احراز هویت NewSOCKS5ProxyAuth

تابع پراکسی ساکس۵ با احراز هویت(addr: رشته، username: رشته، password: رشته): پراکسی
پراکسی SOCKS5 با نام کاربری و گذرواژه.

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

شماره‌گیری Dial

تابع شماره‌گیری(p: پراکسی، target_host: رشته، target_port: صحیح): tcp.Conn
از راه پراکسی به مقصد وصل می‌شود و اتصال TCP آماده برمی‌گرداند؛ اگر به پراکسی نرسد یا پراکسی نپذیرد، اتصالی نامعتبر (با تی سی پی.اتصال معتبر بررسی کنید). دست‌دهی بی‌مهلت منتظر می‌ماند.
net-proxy-Dial.salam
واردسازی شبکه.پراکسی
واردسازی شبکه.تی سی پی

تابع ریشه:
    پ := پراکسی.پراکسی ساکس۵ جدید("127.0.0.1:1080")
    ا := پراکسی.شماره‌گیری(پ، "example.com"، ۸۰)
    ناپایا ز := پراکسی.زنجیره جدید()
    پراکسی.افزودن(ز، پ)
    ا۲ := پراکسی.شماره‌گیری زنجیره‌ای(ز، "example.com"، ۸۰)
    سرچاپ تی سی پی.اتصال معتبر(ا)، تی سی پی.اتصال معتبر(ا۲)
پایان

زنجیره جدید NewChain

تابع زنجیره جدید(): زنجیره پراکسی
زنجیره‌ی خالی.

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

افزودن Add

تابع افزودن(c &: زنجیره پراکسی، p: پراکسی)
پراکسی را به انتهای زنجیره اضافه می‌کند.

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

شماره‌گیری زنجیره‌ای DialChain

تابع شماره‌گیری زنجیره‌ای(c: زنجیره پراکسی، target_host: رشته، target_port: صحیح): tcp.Conn
از راه همه‌ی پراکسی‌های زنجیره، به ترتیب، به مقصد وصل می‌شود؛ زنجیره‌ی خالی مستقیم به مقصد وصل می‌شود.

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