الوكيل المحلي لتصفية حركة المتصفح

أريد أن أتحدث عن عملية التطوير ومشاركة الخادم الوكيل ، الذي أستخدمه لتصفية جميع أنواع القمامة والمهام الأخرى التي تتطلب المشاهدة أو التدخل في حركة مرور المتصفح. ربما هناك بالفعل وظيفة مشابهة في مكان ما ، لكنني أردت أن أجعلها مخصصة لاحتياجاتي مع إمكانية إلحاق رمز في الوقت الحقيقي بأي تافه مطلوب على الفور. حسنًا ، في ظل الأشياء الصغيرة أيضًا ، لكنها أطول.


في البداية ، كانت المهمة هي تبسيط زيارة المواقع من خلال اتصال بطيء (حوالي 5-10 كيلوبايت / ثانية مع تأخيرات). هناك مجالان رئيسيان: 1) لقطع كل ما هو غير ضروري (في المقام الأول الإعلان) ، و 2) لتخزين كل شيء يمكن تخزينه في ذاكرة التخزين المؤقت دون الإضرار بوظائف المواقع التي تمت زيارتها ، حتى عندما لا تسمح المواقع نفسها بالتخزين المؤقت في رؤوس http ، أو حتى من الواضح أنهم يتدخلون بإضافة علامة استفهام برقم عشوائي بعد عناوين URL للملفات الثابتة.


تحذير: تم تنفيذ التطبيق الموضح أدناه لنظام Linux ، يبدو أنه يعمل على نظام * nix آخر ، ولكن حتى تجميعه على Windows لم يتم اعتباره (على الرغم من وجود فرصة للتكيف ، بالطبع).


مسودة: nginx + php-fpm


لم أكن أرغب في قضاء كل هذا الوقت ، لذلك تقرر تهيئة حزمة nginx + php-fpm بسرعة ، حيث تم تحليل أول اتصالات واردة ، بما في ذلك https وإعادة توجيهها جميعًا ، دون تحليل المضيفين وعناوين URL ، إلى نفس نص php . كان هناك أيضًا برنامج C صغير يحول بروتوكول http-proxy إلى حركة مرور http (s) عادية. أي أنها حولت الطلبات GET http://host/path HTTP/1.xإلى GET /path HTTP/1.x(اسم المضيف لا يزال في رأس المضيف) وأرسل جميع روابط CONNECTs إلى nginx المحلي. كما اتضح لاحقًا ، http://hostلم يكن من الضروري الإزالة من طلبات http ، حيث يقبلها nginx بنفس الطريقة المعتادة.


قام سكربت PHP بدوره بتجميع الطلب المتحلل في متغيرات مختلفة ، متصلة عبر fsockopen () بالخادم الهدف (يوجد دعم SSL مدمج) ، وأرسل طلب http الذي تم جمعه ، واستلم الاستجابة وأرسلها إلى المتصفح باستخدام الرأس () و صدى صوت. لم يتم عمل النص البرمجي تمامًا من الصفر ، وذلك بفضل إفيلين لاشانس معينة لـ https://github.com/eslachance/php-transparent-proxy (ولكن لا يزال ، مع الإشارة إلى أن الغرض منه مختلف قليلاً ، وبالتالي كان من المستحيل نسخه).


كانت هناك مشكلتان

-, URL , POST- , Content-Type — php- , $_POST[] , , ( ). php 5.4 enable_post_data_reading — off, 'php://input'. $_POST $_FILES, , , .


-, nginx , " " firefox . , . , . ( ), , .


. , host host/path ( php- ). , ( — ). , . GET 200, — . — , , ( , ) content-type . : http-, content-type . , , , , , .


, , , .


( - , — ).


3-4 - — nginx php C.



( ), -, . https, - ( ), SSL - php .


OpenSSL. , , . , -, ( ), - ( ), - API OpenSSL ( ), API, ( ) ssl- ( , , ).


OpenSSL SSL

, - API TLS, , , (, , , , ), ASN1. , API , RFC . .


SSL/TLS-


, , SSL/TLS, , , . : , , , . .


, (accept) , SSL/TLS, ( SSL/TLS-, ), , . http- https-, , .


, : , , .


ssl-server-wrapper ssl-client-wrapper. , — , , SSL- , .



$ host ya.ru                        -  ip-
ya.ru has address 87.250.250.242
$ ./ssl-client-wrapper
T/etc/ssl/certs/ca-certificates.crt    -      RootCA
C87.250.250.242:443/ya.ru              -       SNI

( , ):


DEBUG: cert[-1] subject = /C=RU/O=Yandex LLC/OU=ITO/L=Moscow/ST=Russian Federation/CN=*.yandex.az
DEBUG: cert[-1] issuer = /C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
DEBUG: cert[0] subject = /C=RU/O=Yandex LLC/OU=ITO/L=Moscow/ST=Russian Federation/CN=*.yandex.az
DEBUG: cert[0] issuer = /C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
DEBUG: cert[1] subject = /C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
DEBUG: cert[1] issuer = /C=PL/O=Unizeto Technologies S.A./OU=Certum Certification Authority/CN=Certum Trusted Network CA
DEBUG: cert[2] subject = /C=PL/O=Unizeto Technologies S.A./OU=Certum Certification Authority/CN=Certum Trusted Network CA
DEBUG: cert[2] issuer = /C=PL/O=Unizeto Sp. z o.o./CN=Certum CA

trusted


DEBUG: cert[-1] issued by cert[1]
DEBUG: cert[1] issued by cert[2]
DEBUG: cert[2]=cert[*0] was not issued by something from trusted-cert-store - chain incomplete, trying to recover
DEBUG: cache miss at ./cert-pin/cache/9nqv0qm41tlxyel95bbods0famxjagbx.0
DEBUG: downloading AIA issuer cert: http://repository.certum.pl/ca.cer
DEBUG: cert[*0] issued by cert[*1]
DEBUG: cert[*1] is self-signed, chain ended

, "Certum CA" Root CA, , (cert[2]) http://repository.certum.pl/ca.cer ; (cert[*1]), . , Root CA "Certum Trusted Network CA", .


:


DEBUG: check wildcard '*.yandex.az' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.tm' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.com.ua' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.de' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.jobs' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.net' against needed name 'ya.ru'
DEBUG: check wildcard '*.xn--d1acpjx3f.xn--p1ai' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.com.ge' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.fr' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.fr' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.kz' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.aero' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.jobs' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.ee' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.com' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.tm' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.ru' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.ru' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.lv' against needed name 'ya.ru'
DEBUG: check wildcard '*.yandex.lt' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.az' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.net' against needed name 'ya.ru'
DEBUG: check wildcard 'yandex.lt' against needed name 'ya.ru'
DEBUG: check wildcard 'ya.ru' against needed name 'ya.ru'

:


DEBUG: protocol = TLSv1.2
DEBUG: cipher = ECDHE-RSA-AES128-GCM-SHA256
DEBUG: verify_result = 0
DEBUG: server_cert subject: /C=RU/O=Yandex LLC/OU=ITO/L=Moscow/ST=Russian Federation/CN=*.yandex.az
DEBUG: server_cert issuer: /C=RU/O=Yandex LLC/OU=Yandex Certification Authority/CN=Yandex CA
OK: connection to 87.250.250.242:443/ya.ru established

, http-


GET / HTTP/1.0
Host: ya.ru
Connection: close

HTTP/1.1 200 Ok
Accept-CH: Viewport-Width, DPR, Device-Memory, RTT, Downlink, ECT
Accept-CH-Lifetime: 31536000
(...)


, .


nginx , . , \r\n \n , , , Content-Length, . Chunked encoding — , http-, .


, , — , php, . ( , , ..), php- , , "" ( C PHP), " -" . ( ) "" "" include ( ).


, 2 . — - ( ), , .



  1. SSL/TLS-, ssl-telnet. - ( -), . , . OpenSSL ( , - ). .


    • : ( ), ( ), (, , — ). ( , ). , , .
    • , , trusted root CA .

  2. , , ssh port forwarding ( helpers/remote.c proxy.c "--proxy". . SSL/TLS , "" . , .


  3. : , , , , raw- ( real-time ).


  4. /etc/hosts : - , , .


  5. , , , . ( , ), . " , — ", . , , , " - ".


    • — , , . - ( offline.flag , ). , , , ( POST- ), , , — .

  6. , . , handle/inc.rewrite.c


  7. dashboard ( ) .
    ./dashboard --basedir=/path/to/proxy/base --highlight --loop


  8. . , , , , , . , - — , " ".




(+)
(-) - OpenSSL
(+)
(+-) #define
(+-) IPv6
(-)
(-)
(-) Access-Control-Allow-Origin '*' — .
(-) ,
(-) ( raw ) — , localhost- , , - ( ) 10


/


C-, zlib ( gzip http-), openssl ( ssl-). Debian zlib1g-dev libssl-dev. () .


, ( ) (, Makefile, make) build-all.sh.


: fproxy/build2.sh, fproxy/config.h ( /etc/ssl/certs/ca-certificates.crt ). (helpers/) #define (config.h ), .


, , () . , ( ), — , ( #define-). build-all.sh .


.


. prepare-dir.sh — fproxy-target/ ( ).


:
cache/cache_real/.
cache_real/, — 2 , .
saved/saved_real/.
saved_real/-, 2-. .
cert-pin/certs/( , / , ).
cert-pin/queue/, .
cert-pin/cache/, ( , ).
dyn-certs/.
hist/( , ).
internal/AIA .
log/.
pem/.
proxy_temp/.
tmp/.
dyn-cert-serial( — '0' ).
mincache.date0, .
offline.flag0, "-" — saved_real/ , , — .
rules_*.txt, .


— ( fproxy-target/, prepare-dir.sh).


-. , , , . " " , root , 0640 0750. world-readable , , - , , MITM.


dashboard BASE/log/dashboard .


127.0.0.10:3128. 127.0.0.10 ( ) , - .


— , , .



: .


, , "-", . , .


— (, , , ) , , .


, - .


All Articles