«הדפדפן פותח אתרים חיצוניים, ורק אפליקציית העסק אינה מגיעה ל-API החיצוני.» «עובד במכונת הפיתוח, ונכנס לפסק זמן ברשת הלקוח.» «מתקשר כשאני מריץ ידנית, ונכשל ברגע שאני הופך לשירות Windows.» — כאשר מריצים אפליקציית עסק בסביבה עם פרוקסי ארגוני, ייעוץ מסוג זה הוא מהנפוצים ביותר.
ברוב המקרים הסיבה אינה תקלת שרת פרוקסי ואינה באג באפליקציה. ב-Windows יש כמה משפחות נפרדות של מה שאנשים קוראים «הגדרות פרוקסי», ואילו הגדרות מי קורא נבדל לפי אפליקציה (לפי מחסנית ה-HTTP שהיא משתמשת) ולפי חשבון ההרצה — אי-ההתאמה הזו. ההגדרות שהדפדפן קורא, שאלו שירות קורא, ואלו ש-HttpClient של .NET קורא יכולות כל אחת להיות דבר אחר. ברגע שהמבנה הזה בראש, בידוד «עובד בדפדפן, אבל…» נעשה מהיר להפתיע.
המאמר מיועד לאנשי IT בחברות קטנות ובינוניות ולמפתחי אפליקציות Windows. הוא קושר בתמונה אחת את שלוש משפחות הגדרות הפרוקסי — WinINET, WinHTTP ומשתני סביבה — קונפיגורציה אוטומטית של PAC ו-WPAD, ההבדל בפתרון פרוקסי בין .NET Framework ל-.NET (Core ואילך), פרוקסי מזהה (407), בדיקת TLS, ואת הליך הבידוד המעשי. דפוסי יצירת HttpClient ותכנון פסקי זמן עצמם מכוסים ב-«אל תעטפו HttpClient ב-using», ולכן מאמר זה מתרכז בפתרון פרוקסי.
1. המסקנה תחילה
- הגדרות פרוקסי של Windows אינן דבר אחד; יש לפחות שלוש משפחות. (1) הגדרות WinINET לכל משתמש (דף «פרוקסי» באפליקציית ההגדרות = אפשרויות האינטרנט הישנות), (2) הגדרות מכונה של WinHTTP (
netsh winhttp), ו-(3) משתני הסביבהHTTP_PROXY/HTTPS_PROXY. איזו נקראת מוכרעת בצד האפליקציה.12 - «הפרוקסי» שרואים באפליקציית ההגדרות הוא הגדרות לכל משתמש של WinINET. דפדפנים ואפליקציות אינטראקטיביות קוראים אותן; שירותי Windows לא. WinINET אינו נתמך לשימוש בשירות; שימוש שירות הוא עבודת WinHTTP.13
- הסיבה הנפוצה ביותר ל-«עובד ידנית ולא כשירות» היא הבדל חשבון הרצה. LocalSystem וחשבון שירות אינם רואים את הפרוקסי לכל משתמש שמנהל הגדיר על המסך שלו.34
netsh winhttp set proxyהוא הגדרה סטטית; אינו מטפל ב-PAC, בגילוי אוטומטי או באימות פרוקסי. אם רוצים להגדיר PAC או WPAD לכל מכונה, צריך את צדnetsh winhttp set advproxy.42- תוצאות PAC משתנות לכל URL. הפונקציה
FindProxyForURLשל קובץ ה-PAC מקבלת URL ומארח ומחזירה רשימת פרוקסי או חיבור ישיר (DIRECT). «האתר ההוא עובד, ורק ה-API הזה לא» יכול להיות ענף PAC.56 - HttpClient ב-.NET (Core ואילך) מאתחל את פרוקסי ברירת המחדל בסדר משתני סביבה → הגדרות פרוקסי משתמש Windows. אם אחד מ-
HTTP_PROXY,HTTPS_PROXYאוALL_PROXYמוגדר, הוא קודם להגדרות מערכת ההפעלה, ולכן יכול לקרות התאונה «מישהו השאיר משתנה סביבה».7 - ברירת המחדל של .NET Framework היא אפשרויות האינטרנט של חשבון ההרצה, וניתן לדרוס אותה ב-
defaultProxyב-app.config. הגדרות קובץ התצורה קודמות להגדרות המערכת.89 - 407 הוא שגיאת אימות פרוקסי; זה דבר אחר מ-401 (אימות שרת). הסכמות כוללות Negotiate, NTLM ו-Basic, וב-.NET מעבירים אישורים עם
DefaultProxyCredentialsאוWebProxy.UseDefaultCredentials. שימו לב שתחת חשבון שירות תוכן «אישורי ברירת המחדל» משתנה.101112 - פרוקסי בדיקת TLS מחזיק רק כסט עם הפצת אישור רשות האישורים הפנימית. מכונות וזמני ריצה שלא קיבלו אותו מקבלים שגיאת אימות אישור. פתרו בהפצה למאגר האישורים, לא בביטול האימות באפליקציה.134
במשפט אחד: בכל פעם שאומרים «בדקתי את הגדרות הפרוקסי», תמיד להיות מסוגלים לומר איזו משלוש המשפחות בדקתם, ומאיזה חשבון — זה נושא המאמר.
2. ב-Windows יש שלוש משפחות של «הגדרות פרוקסי»
תחילה, המפה הכוללת. הנתיבים שאפליקציית Windows משתמשת בהם למצוא פרוקסי ארגוני נופלים לשלוש המשפחות האלה.
| משפחת הגדרות | היכן מגדירים / הפקודה | היקף | מי קורא בעיקר |
|---|---|---|---|
| (1) WinINET (אפשרויות אינטרנט) | הגדרות → רשת ואינטרנט → פרוקסי, inetcpl.cpl |
לכל משתמש (ברירת מחדל) | דפדפנים, אפליקציות שולחן אינטראקטיביות, ברירת מחדל של .NET Framework |
| (2) WinHTTP (הגדרות מכונה) | netsh winhttp set proxy / set advproxy |
מכונה | שירותי Windows, חלק מרכיבי מערכת ההפעלה |
| (3) משתני סביבה | HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY |
תהליך (עוברים בירושה לפי מקום ההגדרה) | HttpClient ב-.NET (Core ואילך), curl, כלים חוצי-פלטפורמה כמו Node.js ו-Python |
(1) הוא מה שאנשים מזהים בדרך כלל כ-«הגדרות הפרוקסי של Windows»; המהות היא תצורת WinINET. היסטורית אלו אפשרויות האינטרנט של Internet Explorer, וכברירת מחדל הן נשמרות לכל משתמש.4
(2) הוא ברירת המחדל לכל מכונה להקשרים כמו שירות שבהם «אין משתמש מחובר». (3) הוא בעיקר מוסכמת כלים שבאים מעולם חוצה-הפלטפורמות; ב-Windows גם .NET (Core ואילך) ו-curl וכדומה קוראים אותם.7
הנקודה החשובה היא שאיזו משפחה נקראת מוכרעת בצד האפליקציה, לא בצד ההגדרות. אם האפליקציה משתמשת ב-WinINET פנימית היא קוראת (1); אם WinHTTP, (2) (או דריסה ספציפית לאפליקציה); אם .NET (Core ואילך), (3) ואז (1). לכן בדרך כלל זה לא «הגדרות הפרוקסי נכונות אבל עדיין לא מתחבר»; המציאות היא «המשפחה שהאפליקציה קראה הייתה משפחה אחרת מזו שבדקתם».
flowchart TB
accTitle: שלוש משפחות של הגדרות פרוקסי Windows
accDescr: WinINET הוא הגדרות לכל משתמש ואפשרויות אינטרנט, WinHTTP הוא ברירת מחדל של המכונה דרך netsh, ומשתני סביבה הם בהיקף תהליך. איזו משפחה נקראת מחליטה האפליקציה, לא צד ההגדרות
fam{"איזו משפחה?"}
fam --> wininet["הגדרות WinINET לכל משתמש"]
fam --> winhttp["הגדרות מכונה של WinHTTP"]
fam --> env["HTTP_PROXY וחברים"]
wininet -.-> r1["דפדפנים ואפליקציות שולחן"]
winhttp -.-> r2["שירותים וחלקי מערכת"]
env -.-> r3[".NET Core+ ו-curl"]
איור 1: שלוש משפחות זו לצד זו. האפליקציה בוחרת איזו היא קוראת.
אם מפעילים את מדיניות הקבוצה «הפוך הגדרות פרוקסי למכונה (ולא למשתמש)», אפשר להעביר את (1) לכל מכונה ולהחיל את אותן הגדרות על כל משתמש. עם MDM (Intune וכדומה) אפשר להגדיר לכל מכשיר עם NetworkProxy CSP.4
3. WinINET ו-WinHTTP — לאפליקציות אינטראקטיביות ולשירותים
3.1. ההבדל בתפקידים
WinINET ו-WinHTTP שניהם מחסניות לקוח HTTP מובנות ב-Windows, אך הם מניחים שימושים שונים.
- WinINET: מכוון לאפליקציות שולחן אינטראקטיביות. הוא יורש אוטומטית את אפשרויות האינטרנט של המשתמש (פרוקסי, עוגיות, מטמון אישורים) ואף יכול להציג ממשק הזנת אישורים אם צריך. שימוש בשירות או בתהליך דמוי-שירות אינו נתמך.1
- WinHTTP: מכוון לשירותים ולצד השרת. הוא תומך בהרצה תחת חשבון שירות, בהתחזות שרשור ובבידוד הפעלה; בתמורה אינו חולק את הגדרות הדפדפן של המשתמש, עוגיות או אישורים. גם אינו מציג ממשק.3
ההנחיה של Microsoft עצמה ברורה באותה מידה: «השתמשו ב-WinINET אלא אם אתם רצים בתוך שירות, או בתהליך דמוי-שירות שזקוק לבידוד הפעלה ולהתחזות» — במילים אחרות, אם זה שירות, השתמשו ב-WinHTTP.1
flowchart TB
accTitle: WinINET לאפליקציות אינטראקטיביות, WinHTTP לשירותים
accDescr: WinINET יורש את אפשרויות האינטרנט של המשתמש המחובר ואינו נתמך בשירות. WinHTTP רץ תחת חשבון שירות בלי ממשק ואינו חולק את הגדרות הדפדפן של המשתמש
q{"אפליקציית שולחן אינטראקטיבית?"}
q -->|"כן"| ie["WinINET"]
q -->|"שירות או דמוי-שירות"| wh["WinHTTP"]
ie -.-> ieNote["קורא אפשרויות אינטרנט של המשתמש"]
wh -.-> whNote["הגדרות מכונה, בלי ממשק"]
איור 2: אפליקציות אינטראקטיביות משתמשות ב-WinINET. שירות משתמש ב-WinHTTP.
3.2. פעולות netsh winhttp בסיסיות
פרוקסי ברירת המחדל של המכונה של WinHTTP מופעל עם netsh.2
:: Display the current WinHTTP proxy settings
netsh winhttp show proxy
:: Set a static proxy (with a bypass list)
netsh winhttp set proxy proxy-server="proxy.example.co.jp:8080" bypass-list="*.example.co.jp;<local>"
:: Import the Internet Options (WinINET) settings
netsh winhttp import proxy source=ie
:: Return to the default (DIRECT)
netsh winhttp reset proxy
שני אילוצים לזכור כאן.
netsh winhttp set proxyהוא הגדרה סטטית. הוא אינו מטפל בגילוי אוטומטי של פרוקסי, ולא בציון URL של PAC, ולא באימות פרוקסי.4import proxy source=ieמעתיק רק את ההגדרות הסטטיות באותו רגע; אינו עוקב אחרי שינויים מאוחרים בצד אפשרויות האינטרנט. כאשר צריך תצורה לכל מכונה שכוללת PAC או גילוי אוטומטי, הגדירו את ההגדרות המפורטות בצורת JSON (Proxy,ProxyBypass,AutoconfigUrl,AutoDetect) עםnetsh winhttp set advproxy.2
3.3. המלכודת הנפוצה ביותר: שירות אינו קורא את הגדרות IE של המשתמש
הדפוס שרואים הכי הרבה בשטח, בסדר הזמן, נראה כך.
- מפתח מריץ את הכלי במחשב שלו → הגדרות הפרוקסי לכל משתמש (1) נכנסות לתוקף ועובד
- בייצור משאירים אותו תושב כשירות Windows (איך לבנות ולהפעיל שירותי Windows) תחת LocalSystem
- ההגדרות הנראות מ-LocalSystem הן דבר אחר (הגדרות לכל משתמש בלתי נראות, והגדרות מכונה של WinHTTP לא מוגדרות = DIRECT) → מנסה חיבור ישיר ל-API החיצוני ונכנס לפסק זמן
זה לא «לא עובד אף שזו אותה מכונה»; גם באותה מכונה, חשבון הרצה אחר פירושו שסט אחר של הגדרות פרוקסי נראה. לתהליך שמתקשר גם כשאף משתמש אינו מחובר, הגישה הנכונה היא להכין הגדרות לכל מכונה בצורה שמחסנית ה-HTTP של אותו תהליך באמת קוראת. לאפליקציה מקורית או רכיב Windows שמשתמש ב-WinHTTP, הגדרות WinHTTP של netsh נכנסות לתוקף.4 HttpClient ב-.NET (Core ואילך), לעומת זאת, אינו קורא את הגדרות המכונה של WinHTTP (ראו פרק 5), ולכן לשירות .NET מגדירים משתנה סביבה מערכתי (HTTPS_PROXY וכדומה) או מציינים HttpClientHandler.Proxy במפורש מהגדרות האפליקציה.
התאונה קורה גם בכיוון השני. אם אופים פרוקסי סטטי למחשב נייד שנע בין הרשת הארגונית לחוץ עם netsh winhttp set proxy, אותו פרוקסי אינו נגיש מחוץ לחברה והתקשורת מתה לגמרי. התייחסו להגדרה סטטית של מכונה כאמצעי שמכוון לשרתים שתצורת הרשת שלהם אינה משתנה.4
flowchart TB
accTitle: מדוע שירות אינו רואה את הגדרות IE של המשתמש
accDescr: הרצת מפתח קוראת הגדרות WinINET לכל משתמש ועובדת. כ-LocalSystem ההגדרות האלה בלתי נראות. אפליקציית WinHTTP מקורית אז הולכת אחרי הגדרות מכונה לא מוגדרות (DIRECT). שירות .NET Core+ עדיין משתמש במשתני סביבה או handler.Proxy מפורש ואינו עובר ל-netsh winhttp
dev["הרצה ידנית כמשתמש"] --> ok["הגדרות WinINET לכל משתמש חלות"]
svc["שירות Windows כ-LocalSystem"] --> miss["הגדרות לכל משתמש בלתי נראות"]
miss --> stack{"איזו מחסנית HTTP?"}
stack -->|"WinHTTP"| direct["WinHTTP לא מוגדר = DIRECT"]
stack -->|".NET Core+"| env["משתני סביבה או handler.Proxy"]
direct --> fail["ה-API החיצוני נכנס לפסק זמן"]
איור 3: אותה מכונה, חשבון אחר, סט אחר של הגדרות פרוקסי נראות.
4. PAC ו-WPAD — מה «קונפיגורציה אוטומטית» באמת
4.1. קובצי PAC ו-FindProxyForURL
קובץ PAC (Proxy Auto-Configuration) הוא JavaScript (ECMAScript) שמחשב «איזה פרוקסי להשתמש ל-URL הזה», והוא תמיד מכיל פונקציה בשם FindProxyForURL(url, host). הפונקציה מחזירה רשימת פרוקסי שיש להשתמש בהם, או ערך החזרה מיוחד (DIRECT) שפירושו שמותר להתחבר ישירות בלי פרוקסי.5
function FindProxyForURL(url, host) {
// Internal domains and private addresses go direct
if (dnsDomainIs(host, ".example.co.jp") ||
isInNet(host, "10.0.0.0", "255.0.0.0")) {
return "DIRECT";
}
// Everything else goes through a proxy. Fall back to the next if the first is unavailable
return "PROXY proxy1.example.co.jp:8080; PROXY proxy2.example.co.jp:8080; DIRECT";
}
שתי תוצאות מעשיות נובעות.
- פתרון פרוקסי חייב להיעשות לכל URL. כי PAC יכול להחזיר פרוקסי אחר או חיבור ישיר לפי ה-URL (המארח), גם תכונת הפרוקסי האוטומטי של WinHTTP מתוכננת להעביר את URL הבקשה ולשאול בכל פעם.6 «הדפדפן רואה אתר אחר» אינו הוכחה שה-API הבעייתי לוקח את אותו נתיב.
- DIRECT הוא הוראה «ללכת בלי פרוקסי». אם תעבורה שאמורה להיות פנימית אינה מופיעה ביומן הפרוקסי כלל, חשדו תחילה ש-PAC החזיר DIRECT (או שפגע ברשימת עקיפה).
4.2. גילוי אוטומטי דרך WPAD
הפעילו «גלה הגדרות אוטומטית» והמכונה מחפשת את מיקום קובץ ה-PAC בפרוטוקול WPAD (Web Proxy Auto-Discovery). בתצורה טיפוסית DHCP מוסר URL של PAC, או משתמשים ב-DNS לחפש מארח בשם wpad וה-PAC מורד מ-URL כמו http://wpad/wpad.dat.14
כלומר, «גילוי אוטומטי» אינו קסם; זה מנגנון שעובד רק ברשת שכבר הקימה סידור WPAD ב-DHCP/DNS. הפעלת גילוי אוטומטי לבדו ברשת בלי סידור כזה רק מוסיפה זמן המתנה לכישלון גילוי.
flowchart TB
accTitle: PAC פותר פרוקסי לכל URL, WPAD רק מוצא את ה-PAC
accDescr: FindProxyForURL מקבל URL ומארח ומחזיר רשימת פרוקסי או DIRECT. WPAD מאתר את ה-PAC רק דרך DHCP או DNS. לקוח שאינו יכול להעריך PAC נופל לפרוקסי סטטי או למשתני סביבה
url["URL הבקשה"] --> pac["FindProxyForURL"]
pac -->|"רשימת פרוקסי"| via["לעבור דרך פרוקסי"]
pac -->|"DIRECT"| dir["להתחבר בלי פרוקסי"]
wpad["WPAD דרך DHCP או DNS"] -.-> pac
nopac["לקוח שאינו מעריך PAC"] -.-> fb["הגדרות סטטיות או משתני סביבה"]
איור 4: PAC מחליט לכל URL. WPAD רק מוצא את קובץ ה-PAC.
4.3. איך מתנהגים לקוחות שאינם יכולים להעריך PAC
לא כל לקוח יכול להעריך PAC.
- ההגדרות הסטטיות של
netsh winhttp set proxyאינן מעריכות PAC.4 - כלים שמשתמשים בסגנון משתנה הסביבה
HTTP_PROXYיכולים, ככלל, לכתוב רק URL פרוקסי קבוע (אין מקום לכתוב URL של PAC).7 - לאפליקציה מקורית שמשתמשת ב-WinHTTP ישירות, זה תלוי איך נפתחה ההפעלה. אפליקציה שנפתחה עם
WinHttpOpenב-Windows 8.1 ואילך עם ציוןWINHTTP_ACCESS_TYPE_AUTOMATIC_PROXYגורמת ל-WinHTTP לפתור אוטומטית את הגדרות הפרוקסי של המערכת/המשתמש (כולל WPAD/PAC) לכל בקשה.15 אם נפתחה עםWINHTTP_ACCESS_TYPE_DEFAULT_PROXYהישן יותר (מיושן מ-8.1 ואילך) או דומה, פרוקסי אוטומטי אינו משולב במחסנית ה-HTTP, והאפליקציה צריכה לקרוא בעצמה ל-WinHttpGetProxyForUrlולהחיל את התוצאה על הבקשה. כלומר, ביישום ישן יותר, PAC יכול להיות נוכח ועדיין לא בשימוש.5
«הדפדפן הולך לפרוקסי הנכון דרך PAC, אך אפליקציית העסק אינה קוראת PAC ומנסה חיבור ישיר ונכשלת» — זו עוד אי-התאמה קלאסית. ברשת שמופעלת ב-PAC צריך להחליט על נפילה — הגדרות סטטיות או משתני סביבה — ללקוחות שאינם יכולים לקרוא PAC.
5. פתרון פרוקסי ב-.NET — Framework ו-Core ואילך הם דברים שונים
אילו הגדרות פרוקסי אפליקציית .NET קוראת נבדל כברירת מחדל בין .NET Framework ל-.NET (Core ואילך). מערבבים את השניים ובודקים אפליקציית .NET 8 בידע של עידן Framework ומפספסים.
5.1. .NET Framework — ברירת המחדל אפשרויות אינטרנט, נדרסת ב-defaultProxy
ב-.NET Framework, HttpWebRequest ו-HttpClient שיושב עליו משתמשים בפרוקסי ברירת המחדל אלא אם מציינים Proxy במפורש. פרוקסי ברירת המחדל מוכרע בשילוב של הגדרות האינטרנט של המערכת (הגדרות WinINET של חשבון ההרצה) וקובץ התצורה, והגדרות קובץ התצורה קודמות.8
אפשר לשלוט בברירת מחדל זו באלמנט system.net/defaultProxy ב-app.config (או machine.config).9
<configuration>
<system.net>
<!-- useDefaultCredentials: whether to send default credentials to an authenticating proxy -->
<defaultProxy enabled="true" useDefaultCredentials="true">
<proxy usesystemdefault="true"
proxyaddress="http://proxy.example.co.jp:8080"
bypassonlocal="true" />
<bypasslist>
<add address="[a-z]+\.example\.co\.jp$" />
</bypasslist>
</defaultProxy>
</system.net>
</configuration>
השאירו את אלמנט defaultProxy ריק והגדרות המערכת (אפשרויות האינטרנט) בשימוש; כתבו proxyaddress וכדומה ואלו קודמות. מהתוכנית אפשר להחליף את אותה ברירת מחדל ב-WebRequest.DefaultWebProxy.98
המלכודת מפרק 3.3 חלה גם כאן. כי ברירת המחדל היא «אפשרויות האינטרנט של חשבון ההרצה», אפליקציית .NET Framework שרצה תחת חשבון שירות קוראת סט הגדרות אחר (בדרך כלל ריק) מאלו הנראות בשולחן של המנהל.
5.2. .NET (Core ואילך) — משתני סביבה תחילה, אחר כך הגדרות משתמש של מערכת ההפעלה
ל-HttpClient ב-.NET (Core ואילך) יש מאפיין סטטי HttpClient.DefaultProxy. אלא אם handler מציין פרוקסי במפורש, כל מופע HttpClient משתמש בו. כלל האתחול ב-Windows הוא «קרא משתני סביבה, ואם אינם מוגדרים קרא את הגדרות פרוקסי המשתמש».7
משתני הסביבה שבשימוש הם כדלקמן.7
| משתנה סביבה | משמעות |
|---|---|
HTTP_PROXY |
פרוקסי לבקשות HTTP |
HTTPS_PROXY |
פרוקסי לבקשות HTTPS |
ALL_PROXY |
נפילה כאשר האמור לעיל אינו מוגדר |
NO_PROXY |
רשימה מופרדת בפסיקים של מארחים שלא צריכים להשתמש בפרוקסי |
שלושה דברים לשים לב.
- אם אחד מ-
HTTP_PROXY,HTTPS_PROXYאוALL_PROXYמוגדר, הוא קודם להגדרות הפרוקסי בצד מערכת ההפעלה. הגדרתNO_PROXYבלבד אינה מגדירה פרוקסי ממשתני סביבה, וב-Windows ממשיכים להשתמש בהגדרות פרוקסי המשתמש של מערכת ההפעלה. «הגדרות בלתי נראות» כמו השארתHTTPS_PROXYכמשתנה סביבה מערכתי אחרי ניסוי ישן, או תבנית CI/CD שמזריקה אותו, הן כר גידול לתאונות. NO_PROXYאינו תומך בתווים כלליים (*). כדי להתאים תת-דומיין, שימו נקודה מובילה (.example.comמתאים ל-www.example.comאך לא ל-example.comעצמו).7- מחוץ ל-Windows (מכלי Linux וכדומה), אם משתני הסביבה אינם מוגדרים זה מאותחל בלי פרוקסי. שינוי התנהגות ברירת המחדל של אותה אפליקציה בין Windows ל-Linux הוא דבר לאשר בזמן מעבר למכל.7
5.3. ציון מפורש — HttpClientHandler.Proxy ו-UseProxy
בכל זמן ריצה, העדיפות הגבוהה ביותר היא ציון מפורש על ה-handler. ציון HttpClientHandler.Proxy קודם להגדרות מערכת ההפעלה ולקובץ התצורה, ו-UseProxy = false אינו משתמש בפרוקסי כלל.14
using System.Net;
// Use a proxy read from app settings explicitly
var handler = new HttpClientHandler
{
Proxy = new WebProxy("http://proxy.example.co.jp:8080")
{
BypassProxyOnLocal = true,
BypassList = new[] { @"^intra\.example\.co\.jp$" },
UseDefaultCredentials = true // On an authenticating proxy, respond with the running account's credentials
},
UseProxy = true
};
var client = new HttpClient(handler);
// A client that never uses a proxy (for direct internal APIs)
var directHandler = new HttpClientHandler { UseProxy = false };
var directClient = new HttpClient(directHandler);
כאשר אין ציון מפורש והולכים אחרי הגדרות מערכת ההפעלה, לעקיפה אוטומטית של יעדים מקומיים יש כללים. שם שטוח בלי נקודה, כתובת לולאה, יעד שמתאים לסיומת הדומיין של המכונה עצמה וכדומה יכולים להיחשב «מקומיים».14 תופעות כמו «ההתנהגות משתנה אם מציינים כתובת IP» או «פתאום התחיל לעבור בפרוקסי כשהשתמשתי ב-FQDN» יכולות להיגרם משיפוט זה.
סדר העדיפות הוא כדלקמן.
| עדיפות (גבוהה → נמוכה) | .NET Framework | .NET (Core ואילך) |
|---|---|---|
| 1 | ציון מפורש כמו HttpClientHandler.Proxy |
אותו דבר |
| 2 | defaultProxy ב-app.config |
השמה ל-HttpClient.DefaultProxy |
| 3 | אפשרויות האינטרנט של חשבון ההרצה | משתני סביבה (HTTP_PROXY ואחרים) |
| 4 | — | הגדרות פרוקסי משתמש Windows |
flowchart TB
accTitle: פתרון פרוקסי ברירת מחדל ב-Framework מול Core ואילך
accDescr: HttpClientHandler.Proxy מפורש תמיד מנצח. Framework אז משתמש ב-app.config defaultProxy ובאפשרויות האינטרנט של חשבון ההרצה. Core ואילך משתמש בהשמה ל-HttpClient.DefaultProxy, אחר כך משתני סביבה, אחר כך הגדרות פרוקסי משתמש Windows
expl["handler.Proxy מפורש"] --> done["הפרוקסי הזה בשימוש"]
noexpl["אין Proxy מפורש"] --> fw{"איזה זמן ריצה?"}
fw -->|"Framework"| cfg["app.config defaultProxy"]
cfg --> ie["אפשרויות אינטרנט של החשבון"]
fw -->|"Core ואילך"| dp["HttpClient.DefaultProxy"]
dp --> ev["HTTP_PROXY וחברים"]
ev --> user["הגדרות פרוקסי משתמש Windows"]
איור 5: ציון מפורש תמיד מנצח. נתיב ברירת המחדל נבדל לפי זמן ריצה.
6. פרוקסי מזהה — 407 הוא שגיאת האימות של הפרוקסי
6.1. אל תבלבלו 407 עם 401
כאשר מנסים לעבור דרך פרוקסי שדורש אימות, הפרוקסי מחזיר קוד מצב 407 (Proxy Authentication Required) וכותרת Proxy-Authenticate שמונה את הסכמות הזמינות. זה דבר אחר מדרישת האימות של שרת היעד (401 ו-WWW-Authenticate); הצד שמעבירים אליו אישורים והמקום שמגדירים אותם שניהם שונים.10
flowchart TB
accTitle: 407 הוא הפרוקסי, 401 הוא שרת היעד
accDescr: 407 ו-Proxy-Authenticate באים מהפרוקסי. 401 ו-WWW-Authenticate באים משרת היעד. האישורים והמקום שמגדירים אותם נבדלים
req["בקשה יוצאת"] --> who{"מי דורש אימות?"}
who -->|"הפרוקסי"| e407["407 + Proxy-Authenticate"]
who -->|"היעד"| e401["401 + WWW-Authenticate"]
e407 -.-> cred["DefaultProxyCredentials"]
איור 6: 407 הוא אימות פרוקסי. 401 הוא אימות שרת.
הסכמות כוללות Basic, ששולח את שם המשתמש והסיסמה כפי שהם, וסכמות אתגר/תגובה כמו Negotiate (Kerberos/NTLM). בסכמת אתגר/תגובה הסיסמה עצמה אינה נוסעת ברשת, והאימות מסתיים בכמה חילופים.10 מנגנון הסכמה שאליה הוא «נופל» מכוסה בפירוט רב יותר ב-«NTLM ו-Kerberos מוסברים בתרשימים».
6.2. איך להעביר אישורים ב-.NET
כאשר רוצים להשתמש בפרוקסי ברירת המחדל שמגיע מהגדרות מערכת ההפעלה ולהעביר רק את האימות, השתמשו ב-HttpClientHandler.DefaultProxyCredentials. אלו האישורים שנשלחים לפרוקסי ברירת מחדל זה כאשר UseProxy = true ו-Proxy = null (= פרוקסי ברירת המחדל של המערכת).11
using System.Net;
var handler = new HttpClientHandler
{
UseProxy = true, // The default. Combined with a null Proxy, this uses the system-default proxy
Proxy = null,
// Respond to 407 with the credentials of the running account (signed-in user or service account)
DefaultProxyCredentials = CredentialCache.DefaultCredentials
};
var client = new HttpClient(handler);
כאשר מציינים את הפרוקסי במפורש, שימו את האישורים בצד WebProxy. בתרחישי לקוח רבים ההמלצה היא להשתמש באישורי ברירת המחדל של המשתמש המחובר ולא בשם משתמש וסיסמה אישיים, ו-WebProxy.UseDefaultCredentials = true הוא זה.12
6.3. בעיית 407 של חשבון השירות
חשבון ההרצה חשוב גם כאן. «אישורי ברירת מחדל» פירושו האישורים של החשבון שמריץ את התהליך. הריצו כמשתמש אינטראקטיבי והאימות לפרוקסי הוא כאותו משתמש; הריצו כשירות LocalSystem והוא כחשבון המחשב.
- אם הפרוקסי מאמת משתמשים דרך Active Directory, הוא אינו יכול לאמת חשבון מחשב או חשבון מקומי, ו-407 נמשך ברגע שהופכים את האפליקציה לשירות
- להפך, בחלק מהסביבות יש פטור אימות בצד הפרוקסי לשירותים (לפי IP מקור או לפי חשבון)
לכן חקירת 407 אינה נסגרת על «הגדרות האפליקציה» לבד; זה סט עם בדיקת תכנון בצד התשתית: האם הפרוקסי יכול לאמת את חשבון ההרצה. לאפליקציה שתהפכו לשירות, צריך להחליט בשלב התכנון אחד מ: להריץ תחת חשבון שירות דומיין (gMSA וכדומה), לשים פטור אימות בצד הפרוקסי, או להקים פרוקסי ממסר פנימי שאינו דורש אימות.
יש גם סגנון שמשבץ אישורים במשתנה סביבה, כמו HTTP_PROXY=http://user:pass@proxy:80807, אך אז סיסמה בטקסט גלוי חשופה במשתנה סביבה (= מידע תהליך), ולכן אינו מומלץ להפעלה שוטפת.
7. HTTPS ופרוקסי — מנהרות CONNECT ובדיקת TLS
7.1. HTTPS עובר דרך פרוקסי כ-«מנהרה»
כאשר משתמשים בפרוקסי ל-HTTPS, הלקוח שולח תחילה לפרוקסי בקשת CONNECT destination-host:443, והפרוקסי פותח מנהרת TCP. בהצלחה הפרוקסי מחזיר 200, ואחרי זה הלקוח ושרת היעד מבצעים את לחיצת היד של TLS בתוך המנהרה. אם המנהרה אינה נפתחת, הפרוקסי מחזיר 407 (נדרש אימות), 502 או דומה.16
במודל זה הפרוקסי אינו יכול לקרוא את תוכן המנהרה (HTTPS מוצפן). מה שנשאר ביומן הפרוקסי הוא שם מארח היעד והאם החיבור הצליח; נתיב ה-URL אינו נראה — זו התנהגות פרוקסי «מעבר».
flowchart TB
accTitle: HTTPS דרך פרוקסי הוא מנהרת CONNECT
accDescr: הלקוח שולח CONNECT לפרוקסי, הפרוקסי פותח מנהרת TCP ומחזיר 200, ואז הלקוח והיעד מבצעים לחיצת יד TLS במנהרה. יומן הפרוקסי רואה את המארח, לא את נתיב ה-URL
cli["לקוח"] -->|"CONNECT host:443"| px["פרוקסי"]
px -->|"200 ומנהרת TCP"| dest["יעד"]
dest -->|"TLS במנהרה"| cli
px -.-> log["יומן: מארח והצלחה בלבד"]
איור 7: פרוקסי מעבר רואה את המארח, לא את הנתיב המוצפן.
7.2. פרוקסי בדיקת TLS ושגיאות אישור
פרוקסי של מוצרי אבטחה, לעומת זאת, כוללים סוג בדיקת TLS (פענוח SSL, שבירה ובדיקה) שמסיים TLS, בודק את התוכן, ומצפין מחדש לפני העברה. בסכמה זו אישור השרת שמוצג ללקוח אינו האמיתי; הוא מוחלף באישור שנחתם מחדש על ידי רשות האישורים של הפרוקסי.13
ההנחה שמחזיקה את התצורה הזו היא אפוא «אישור רשות האישורים של הפרוקסי הופץ לשורשים המהימנים של כל לקוח». במכונה שלא קיבלה אותו, או בזמן ריצה שאינו מסתכל על מאגר האישורים של Windows (כלים עם מאגר אמון משלהם), מקבלים שגיאת אימות אישור. ב-.NET זה בדרך כלל עולה כ-HttpRequestException שעוטף AuthenticationException (הודעה מסוג «the remote certificate is invalid»).
עקרונות התיקון הם כדלקמן.
- הפיצו את אישור רשות האישורים הפנימית למאגר «רשויות אישורים שורשיות מהימנות» של המחשב המקומי. הפיצול בין מאגר המשתמש למאגר המחשב מכוסה ב-«מאגר האישורים של Windows בפועל».
- אל תבטלו אימות אישורים בקוד. פתרון עוקף שמחזיר תמיד true מ-
ServerCertificateCustomValidationCallbackהופך לאפליקציה פגיעה שאינה יכולה לגלות איש-באמצע ברגע שהיא יוצאת לרשת חיצונית. - תעבורה עם נעיצת אישור אינה ניתנת לבדיקה מלכתחילה. חיבורים שמוודאים אישור Microsoft ספציפי, כמו שחלק מרכיבי Windows עושים, נכשלים ברגע שהפרוקסי מחליף את האישור, ואין פתרון עוקף מלבד החרגה.4 לתעבורה שמיועדת ל-SaaS כמו Microsoft 365, Microsoft עצמה ממליצה להחריג אותה מפענוח ובדיקה בשכבת הרשת.13
תסמין «כל אתר פנימי נראה, ורק שירות ענן מסוים מייצר שגיאת אישור באפליקציה» צריך לגרום לחשוד תחילה בשילוב של רשימת החרגת בדיקת TLS והנעיצה.
flowchart TB
accTitle: פרוקסי בדיקת TLS חותם מחדש את האישור
accDescr: הפרוקסי מסיים TLS, בודק את התוכן, ומציג אישור שנחתם מחדש על ידי רשות האישורים שלו. האימות מחזיק רק אם אותה רשות בשורשים המהימנים. אל תבטלו אימות בקוד
real["אישור שרת אמיתי"] --> px["פרוקסי בדיקת TLS"]
px --> fake["נחתם מחדש על ידי רשות הפרוקסי"]
fake --> client["אימות הלקוח"]
client -->|"הרשות בשורשים"| ok["הצלחה"]
client -->|"הרשות חסרה"| err["שגיאת אישור"]
err -.-> fix["הפיצו את הרשות למאגר"]
איור 8: הבדיקה עובדת רק כסט עם הפצת רשות האישורים הפנימית.
8. הליך הבידוד — חמישה צעדים לזהות את האשם
חקרו «לא יכול להתחבר» באופן מכני בסדר הזה.
| צעד | מה עושים | מה לומדים |
|---|---|---|
| (1) שחזור | לגשת ל-URL הבעייתי עם curl.exe -v או Invoke-WebRequest (עדיף באותה מכונה, תחת אותו חשבון) |
אם זו בעיית אפליקציה או בעיית סביבה |
| (2) איסוף הגדרות | לאסוף את שלוש המשפחות: netsh winhttp show proxy, ההגדרות לכל משתמש, ומשתני סביבה |
מה יש באיזו משפחה |
| (3) זיהוי החשבון | לזהות את חשבון ההרצה של האפליקציה היעד (שירות, מתזמן משימות, משתמש אחר) | תחת אילו הגדרות ואילו אישורים היא רצה |
| (4) סיווג השגיאה | להבחין בין 407 / 403 / כשל פתרון שם / פסק זמן / שגיאת אישור | לבודד אימות פרוקסי, דחיית מדיניות, נתיב ובדיקת TLS |
| (5) יומן הפרוקסי | לבדוק את הזמן המתאים ביומן הגישה של שרת הפרוקסי | אם הגיע לפרוקסי בכלל, וכמי אימת |
אפשר לאסוף את (2) בבת אחת עם PowerShell.
# (1) Per-user (WinINET) settings — note that this reads HKCU of the running account
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' |
Select-Object ProxyEnable, ProxyServer, ProxyOverride, AutoConfigURL
# (2) Machine (WinHTTP) settings
netsh winhttp show proxy
# (3) Environment variables
Get-ChildItem env: | Where-Object Name -match 'proxy'
כמה טיפים מעשיים.
- בבדיקת השחזור ב-(1), היו מודעים לאיזו משפחת הגדרות הכלי קורא.
curl.exeהמובנה ב-Windows יכול לציין פרוקסי במפורש עם-x http://proxy:8080, ולאימות TLS הוא בדרך כלל משתמש במאגר האישורים של מערכת ההפעלה (Schannel).Invoke-WebRequestשל Windows PowerShell 5.1 הולך אחרי צד .NET Framework (אפשרויות אינטרנט כברירת מחדל); PowerShell 7 הולך אחרי צד .NET (משתני סביבה תחילה). «curl עובד והאפליקציה לא» עצמו הוא רמז לאי-התאמה בין משפחות תצורה. - אם היעד ב-(3) הוא שירות, בדקו מחדש את (1) ו-(2) תחת אותו חשבון כמו השירות. בדיקה בהפעלה של המנהל עצמו אינה הוכחה למה ש-LocalSystem רואה.
- בסיווג השגיאה ב-(4), קחו את פרק 6 (אימות) כמועמד ראשון ל-407, פרק 7 (בדיקת TLS) לשגיאת אישור, ו-«אינו מגיע לפרוקסי» (נתיב, פתרון שם, חומת אש) לפסק זמן. הדפוס שבו הסיבה היא כלל נכנס של חומת האש של Windows ולא הפרוקסי מכוסה ב-«חומת האש של Windows ואפליקציות עסקיות».
- אם מגיעים ל-(5) ועדיין אין עקבות ביומן הפרוקסי, התעבורה מעולם לא הגיעה לפרוקסי. חשדו בהחלטת DIRECT של PAC, ברשימת עקיפה, או במשתנה סביבה שנשאר, ואם צריך אשרו את היעד בפועל בלכידת מנות («לכידת מנות ב-Windows בפועל — בחירה בין pktmon, netsh trace ו-Wireshark»).
flowchart TB
accTitle: חמישה צעדים לבידוד כשל פרוקסי
accDescr: שחזרו תחת אותו חשבון, אספו את שלוש משפחות ההגדרות, זהו את חשבון ההרצה, סווגו את השגיאה, ואז בדקו את יומן הפרוקסי
s1["שחזור עם curl"] --> s2["איסוף שלוש משפחות"]
s2 --> s3["זיהוי החשבון"]
s3 --> s4["סיווג השגיאה"]
s4 --> s5["בדיקת יומן הפרוקסי"]
s4 -.-> e407["407: אימות"]
s4 -.-> ecert["שגיאת אישור: בדיקה"]
s4 -.-> eto["פסק זמן: לא הגיע"]
איור 9: לכו את חמשת הצעדים לפי הסדר. מחלקת השגיאה בוחרת את הפרק הבא.
9. המלצת תכנון — הפכו את האפליקציה לכזו שאפשר «להגדיר עליה את הפרוקסי»
הפכו את הליך החקירה והוא הופך להנחיית תכנון בצד האפליקציה. לאפליקציית Windows שתספקו לסביבה עם פרוקסי ארגוני, מומלץ כדלקמן.
- הפכו את הפרוקסי לניתן להגדרה מהגדרות האפליקציה. ברירת המחדל היא «ללכת אחרי הגדרות מערכת ההפעלה». ברוב הסביבות ברירת המחדל מספיקה; רק בסביבות החריגות — אי אפשר לקרוא PAC, רץ כשירות, תצורת פרוקסי מיוחדת — אפשרו לציין URL פרוקסי, רשימת עקיפה, ו-«אל תשתמש בפרוקסי» מקובץ הגדרות.
HttpClientHandler.Proxy/UseProxyבסעיף 5.3 הוא נקודת המימוש.14 - כתבו איך יעדים פנימיים (API, מסדי נתונים, שרתי רישוי וכדומה) מטופלים כחריגי פרוקסי. שימו בצורה שאפשר לכתוב בנוהל הפריסה אם הם מוחרגים על ידי PAC DIRECT, רשימת עקיפה, או
NO_PROXY. כללי ההתאמה שלNO_PROXY(בלי תווים כלליים, מה נקודה מובילה אומרת) מובנים לא נכון בהרחבה, ולכן צרפו דוגמאות.7 - תכננו פסקי זמן וניסיונות חוזרים בהנחה שעוברים דרך פרוקסי. אם הפרוקסי למטה או תקוע באימות, מימוש שמחכה לפסק זמן ברירת מחדל ארוך מקפיא גם את הממשק וגם את ההפעלה. הפרידו פסק זמן חיבור קצר יותר, והגבילו ניסיונות חוזרים לבקשות אידמפוטנטיות (פרטי תכנון ב-«אל תעטפו HttpClient ב-using»).
- רשמו ביומן «איזה פרוקסי היה בשימוש». הפכו את האפליקציה עצמה ליכולה לענות על השאלה הראשונה של חקירת כשל.
יומן כמו ב-(4) כבר יעיל אם הוא רושם רק את תוצאת הפתרון. הנקודה היא לגזור את הנתיב מההגדרות (ה-handler) שבאמת השתמשתם בהן כדי להגדיר את הלקוח. אם רושמים HttpClient.DefaultProxy ישירות, תרשמו ערך שאינו מסכים עם הנתיב בפועל כאשר ה-handler מציין Proxy במפורש או שם UseProxy = false.
using System.Net.Http;
// handler is the same instance used to create the HttpClient
// UseProxy=false is always direct. An explicit specification wins; otherwise DefaultProxy is used
var effectiveProxy = handler.UseProxy
? handler.Proxy ?? HttpClient.DefaultProxy
: null;
var target = new Uri("https://api.example.com/v1/orders");
var route = effectiveProxy is null || effectiveProxy.IsBypassed(target)
? "DIRECT"
: effectiveProxy.GetProxy(target)?.ToString() ?? "DIRECT";
logger.LogInformation("HTTP send {Target} route {Route} account {User}",
target, route, Environment.UserName);
אם בהפעלה רושמים פעם אחת «נתיב» ו-«חשבון הרצה» ליעדים העיקריים, הצעדים (1) עד (3) של פרק 8 מסתיימים רק בקריאת היומן. כשאומרים לכם «עובד בדפדפן, אבל…», היכולת לומר מצד האפליקציה «השתמשתי בהגדרה הזו, ובנתיב הזה» היא תנאי של אפליקציה חזקה מול צרות פרוקסי.
flowchart TB
accTitle: הפכו את הפרוקסי לניתן להגדרה ורשמו את הנתיב
accDescr: כברירת מחדל ללכת אחרי הגדרות מערכת ההפעלה, לאפשר URL פרוקסי מפורש או עקיפה או בלי פרוקסי מהגדרות האפליקציה, ולרשום את המסלול שבאמת היה בשימוש יחד עם חשבון ההרצה
def["ברירת מחדל: ללכת אחרי מערכת ההפעלה"] --> exc{"סביבה חריגה?"}
exc -->|"PAC לא נקרא / שירות / מיוחד"| cfg["הגדירו URL, עקיפה, או בלי פרוקסי"]
exc -->|"המקרה הרגיל"| os["השתמשו בברירת המחדל של מערכת ההפעלה"]
cfg --> log["רשמו מסלול וחשבון"]
os --> log
איור 10: הגדירו כשחייבים. תמיד רשמו איזה נתיב היה בשימוש.
10. סיכום
- הגדרות פרוקסי של Windows מתפצלות לשלוש משפחות — הגדרות WinINET לכל משתמש, הגדרות מכונה של WinHTTP, ומשתני סביבה — ואיזו נקראת מוכרעת על ידי האפליקציה (מחסנית ה-HTTP שלה) וחשבון ההרצה.
- WinINET הוא לאפליקציות אינטראקטיביות ואינו נתמך לשימוש בשירות; שימוש שירות הוא עבודת WinHTTP (
netsh winhttp). ל-«עובד ידנית ולא כשירות» חשדו תחילה בהבדל חשבון הרצה. netsh winhttp set proxyהוא הגדרה סטטית ואינו מטפל ב-PAC, בגילוי אוטומטי או באימות. ברשת שמופעלת ב-PAC צריך להחליט איך יטופלו לקוחות שאינם יכולים לקרוא PAC.FindProxyForURLשל PAC מחזיר פרוקסי או DIRECT לכל URL. WPAD עובד רק ברשת שיש בה סידור DHCP/DNS.- ברירת המחדל של .NET Framework היא אפשרויות האינטרנט של חשבון ההרצה (ניתנת לדריסה ב-
defaultProxy); .NET (Core ואילך) הוא משתני סביבה ואז הגדרות פרוקסי משתמש. ציון מפורש (HttpClientHandler.Proxy) תמיד בעדיפות הגבוהה ביותר. - 407 הוא שגיאת אימות פרוקסי; באפליקציה שרצה תחת חשבון שירות הסיבה הטיפוסית היא ש-«אישורי ברירת המחדל» הופכים לאדם אחר.
- פרוקסי בדיקת TLS מניח הפצת אישור רשות האישורים הפנימית, והתשובה הנכונה לשגיאת אישור היא הפצה למאגר האישורים, לא ביטול האימות. תעבורה נעוצה צריכה החרגה.
- בדדו באופן מכני בסדר «שחזור → איסוף שלוש משפחות ההגדרות → זיהוי חשבון ההרצה → סיווג השגיאה → יומן הפרוקסי». בצד האפליקציה, תכנון ש-«יכול להגדיר את הפרוקסי, ורושם את הנתיב שהשתמש בו» הוא המניעה הטובה ביותר.
בפעם הבאה שמייעצים לכם עם «רק אפליקציית העסק אינה מתחברת», שאלו תחילה את זה.
תחת חשבון של מי האפליקציה הזו רצה, ואיזו משלוש משפחות הגדרות הפרוקסי היא קוראת?
השאלה האחת הזו משנה מאוד את הכניסה לחקירה.
מאמרים קשורים
- אל תעטפו HttpClient ב-using — תקשורת HTTP מעשית באפליקציות עסקיות ב-C# (דפוסי יצירה, פסקי זמן, ניסיונות חוזרים)
- לכידת מנות ב-Windows בפועל — בחירה בין pktmon, netsh trace ו-Wireshark
- חומת האש של Windows ואפליקציות עסקיות — רשמו כללים נכנסים מהמתקין
- איך לבנות ולהפעיל שירותי Windows — מבחירה בין מתזמן משימות לשירותים ועד להפיכת BackgroundService לשירות Windows
- NTLM ו-Kerberos מוסברים בתרשימים — מדוע האימות נופל ל-NTLM
- מאגר האישורים של Windows בפועל — משתמש או מחשב, במה כדאי להשתמש?
תחומי ייעוץ קשורים
KomuraSoft LLC מטפלת בחקירת תקלות תקשורת של אפליקציות Windows בסביבות פרוקסי ארגוני, פרוקסי מזהה ובדיקת TLS — «עובד במכונת הפיתוח אך אינו מתקשר ברשת הלקוח», «אחרי שהפכנו לשירות כבר לא הגיע ל-API החיצוני» — ובייעוץ על תכנון תקשורת של אפליקציות עסקיות שמניח סביבת פרוקסי (פריטי הגדרות, פסקי זמן, תכנון יומנים). אפשר להתחיל מסידור שלבי השחזור ואיך לאסוף יומנים.
קישורי עיון
-
Microsoft Learn, WinINet vs. WinHTTP. על ההנחיה להשתמש ב-WinINET אלא אם אתם בשירות או בתהליך שזקוק להתחזות ולבידוד הפעלה, ועל טבלת השוואת התכונות שמכסה מטמון אישורים, הנחיות אישורים, תמיכת שירותים, התחזות, בידוד הפעלה וכדומה. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, netsh winhttp. על התחביר של netsh winhttp show/set/import/reset; proxy-server ו-bypass-list של set proxy; import proxy source=ie; והגדרות פרוקסי מפורטות בצורת JSON (Proxy, ProxyBypass, AutoconfigUrl, AutoDetect) דרך set advproxy. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, About WinHTTP. על כך ש-WinHTTP הוא מחסנית HTTP שתוכננה לשימוש שירות וצד שרת, תומכת בהרצה תחת חשבון שירות ובהתחזות, ואינה חולקת עוגיות, מטמון, אישורים של הדפדפן או אפשרויות האינטרנט של המשתמש. ↩ ↩2 ↩3
-
Microsoft Learn, Using a proxy with Delivery Optimization. על כך ש-netsh winhttp set proxy הוא הגדרה סטטית שאינה תומכת בגילוי אוטומטי, ב-URL של PAC או באימות פרוקסי; על תצורת פרוקסי לכל מכשיר להקשרים בלי משתמש מחובר (NetworkProxy CSP, מדיניות «הפוך הגדרות פרוקסי למכונה»); ועל תעבורה נעוצת-אישור שנכשלת תחת בדיקת TLS וזקוקה להחרגה. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, WinHTTP AutoProxy Support. על כך שסקריפט PAC מכיל פונקציה FindProxyForURL(url, host) שמחשבת רשימת פרוקסי לכל בקשה ומציינת חיבור ישיר בערך החזרה מיוחד, ועל כך ש-API של AutoProxy הישן יותר אינו משלב אוטומטית פרוקסי אוטומטי במחסנית ה-HTTP כך שהאפליקציה צריכה לקרוא ל-WinHttpGetProxyForUrl. ↩ ↩2 ↩3
-
Microsoft Learn, WinHttpGetProxyForUrl function. על כך שזה מימוש של פרוטוקול WPAD, שצריך לקרוא לו לכל URL כי קובץ PAC יכול להחזיר פרוקסי אחר לכל URL, ושהוא תומך גם ב-URL PAC מפורש וגם בגילוי אוטומטי מהרשת. ↩ ↩2
-
Microsoft Learn, HttpClient.DefaultProxy Property. על כך ש-Windows קורא תחילה את משתני הסביבה HTTP_PROXY, HTTPS_PROXY, ALL_PROXY ו-NO_PROXY ואם אינם מוגדרים את הגדרות פרוקסי המשתמש; ש-Linux מאותחל בלי פרוקסי אם משתני הסביבה חסרים; ש-NO_PROXY אינו תומך בתווים כלליים ומשתמש בהתאמת תת-דומיין עם נקודה מובילה; ושאפשר לכלול ב-URL של הפרוקסי שם משתמש וסיסמה. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, Configuring Internet Applications. על כך שאלמנט defaultProxy מגדיר את פרוקסי ברירת המחדל ב-.NET Framework; ש-HttpWebRequest בלי מאפיין Proxy משתמש בפרוקסי ברירת המחדל; ושהגדרות אינטרנט של המערכת והגדרות קובץ התצורה משולבות עם עדיפות לצד קובץ התצורה. ↩ ↩2 ↩3
-
Microsoft Learn, defaultProxy element (network settings). על המאפיינים enabled ו-useDefaultCredentials של אלמנט system.net/defaultProxy, האלמנטים הילדים proxy, bypasslist ו-module, על כך שהגדרות הפרוקסי של המערכת בשימוש אם האלמנט ריק, ועל תצורה עם HttpClient.DefaultProxy במעבר ל-.NET 6 ואילך. ↩ ↩2 ↩3
-
Microsoft Learn, Authentication in WinHTTP. על כך שקוד מצב 407 וכותרת Proxy-Authenticate מוחזרים כאשר נדרש אימות פרוקסי (אימות שרת הוא 401 ו-WWW-Authenticate); על ההבדל בין אימות Basic לסכמות אתגר/תגובה כמו Kerberos; ועל כך שסכמת אתגר/תגובה פירושה ששם המשתמש והסיסמה אינם נוסעים ברשת. ↩ ↩2 ↩3
-
Microsoft Learn, HttpClientHandler.DefaultProxyCredentials Property. על המאפיין שמגדיר את האישורים המשמשים לאימות לפרוקסי ברירת המחדל כאשר UseProxy הוא true ו-Proxy הוא null כך שמשתמשים בפרוקסי ברירת המחדל של המערכת. ↩ ↩2
-
Microsoft Learn, WebProxy.Credentials Property. על כך שמאפיין Credentials הוא האישורים שנשלחים לפרוקסי בתגובה ל-HTTP 407, ועל ההמלצה בתרחישי לקוח רבים להגדיר UseDefaultCredentials ל-true כדי שישתמשו באישורי ברירת המחדל של המשתמש המחובר. ↩ ↩2
-
Microsoft Learn, Understanding implications when using network intermediation to decrypt or manipulate Microsoft 365 traffic at the network layer. על כך שבדיקת TLS (פענוח SSL) היא תצורה שבה פרוקסי או חומת אש מפענחים, בודקים ומצפינים מחדש TLS; שהיא יכולה לגרום לתקלה ולהידרדרות ביצועים בשירותים שמניחים TLS מקצה לקצה; ועל ההמלצה להחריג תעבורה ליעד Microsoft 365 מפענוח ובדיקה בשכבת הרשת. ↩ ↩2 ↩3
-
Microsoft Learn, Make HTTP requests with the HttpClient class. על שתי שיטות התצורה HttpClient.DefaultProxy ו-HttpClientHandler.Proxy; על כך שציון Proxy קודם לקובץ התצורה ולהגדרות המחשב המקומי; על תצורת WPAD הטיפוסית של קבלת קובץ PAC (wpad.dat וכדומה) דרך שם ה-DNS wpad או DHCP; ועל שיפוט עקיפת יעדים מקומיים לפי שם שטוח, לולאה והתאמת סיומת דומיין. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WinHttpOpen function. על משמעות כל ערך dwAccessType. WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY (Windows 8.1 ואילך) מחליט אוטומטית את הפרוקסי מהגדרות פרוקסי מערכת/משתמש ומטפל גם בכשל-מעבר ובאימות אוטומטית, ו-WINHTTP_ACCESS_TYPE_DEFAULT_PROXY מיושן מ-8.1 ואילך. ↩
-
Microsoft Learn, Work with existing on-premises proxy servers. על כך ש-HTTPS יוצא מיוסד בבקשת CONNECT לפרוקסי; שהצלחה מחזירה HTTP 200; ושתגובות כמו 407 (נדרש אימות) או 502 מציינות שהפרוקסי אינו מתיר את התקשורת, ולכן כדאי להמשיך בבידוד עם צוות צד הפרוקסי. ↩
מאמרים קשורים
מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.
רשימת בדיקה לטיפול בטוח בתהליכי ילד ביישום Windows
כדי לטפל בבטחה בתהליכי ילד ביישום Windows, תכנון הבעלות על עץ התהליכים ונוהל הסיום חשוב יותר מבחירת ה-API להפעלה. המאמר מסדר את Job Objec...
הפצת יישום Windows בקובץ אחד - הגבול בין בינארי יחיד לתלות במערכת ההפעלה
כשרוצים לרכז יישום Windows ל-EXE אחד, המאמר מסדר את ההבדל בין ריכוז ההפצה לפריט אחד לבין ביטול התלות במערכת ההפעלה, וכולל .NET, C++, W...
מעמקי הווירטואליזציה של Windows (חלק 3) — מכונות וירטואליות שעולות בשניות: למה WSL2, Windows Sandbox וקונטיינרים כל כך קלים
למה WSL2 ו-Windows Sandbox עולים בשניות ומרגישים כל כך קלים? המאמר מסביר את המנגנונים, מתמונות בסיס דינמיות ומ-direct map דרך הקצאת זיכרו...
מעמקי הווירטואליזציה של Windows (חלק 2) — זיכרון שאפילו הליבה לא יכולה לראות: איך VBS, HVCI ו-Credential Guard עובדים
בהתקנה נקייה על חומרה תואמת, VBS מופעל כברירת מחדל ומשתמש בהיפרווייזור וב-SLAT כדי ליצור בידוד חזק מהליבה. המאמר מסביר את המבנה של VTL, S...
מעמקי הווירטואליזציה של Windows (חלק 1) — היכן Windows שלכם באמת רץ? ההיפרווייזור והמחיצות
כשמפעילים Hyper-V, Windows המארח עצמו רץ מעל ההיפרווייזור כמחיצת השורש. המאמר מסביר את יסודות הווירטואליזציה דרך התפקידים של VT-x, SLAT ...
נושאים קשורים
העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.
נושאים טכניים ב-Windows
שער לנושאי פיתוח Windows, חקירת תקלות וניצול נכסים קיימים.
שירותים הקשורים לנושא הזה
המאמר קשור ישירות לשירותים הבאים.
פיתוח יישומי Windows
יישומים עסקיים, חיבור התקנים וכלי תקשורת, מהגדרת הדרישות ועד הפיתוח.
שאלות נפוצות
שאלות נפוצות בפניות בנושא המאמר.
- הדפדפן מתחבר, ורק אפליקציית העסק אינה עוברת את הפרוקסי הארגוני. מדוע?
- הדפדפן קורא את הגדרות הפרוקסי לכל משתמש של WinINET, אך אפליקציית עסק אינה קוראת בהכרח את אותן הגדרות. אפליקציה שרצה כשירות Windows, או תחת חשבון אחר, מתייעצת בהגדרות הנראות מחשבון זה, בהגדרות המכונה של WinHTTP, או במשתני סביבה. זהו תחילה את חשבון ההרצה, ובדקו את הגדרות הפרוקסי הנראות מחשבון זה הן ב-netsh winhttp show proxy והן בהגדרות המשתמש. אם אפשר לשחזר עם curl.exe או דומה תחת אותו חשבון באותה מכונה, אפשר לטפל בזה כאי-התאמה בין משפחות תצורה ולא כבעיה של האפליקציה.
- הגדרתי netsh winhttp set proxy, אך תעבורת האפליקציה לא השתנתה. מדוע?
- מה ש-netsh winhttp מגדיר הוא ברירת המחדל של המכונה של WinHTTP. זה אינו משפיע על דפדפנים או אפליקציות אינטראקטיביות שקוראות WinINET, ולא על HttpClient של .NET (Core ואילך), שמעדיף משתני סביבה. netsh winhttp set proxy הוא גם הגדרה סטטית; הוא אינו מטפל בקונפיגורציה אוטומטית של PAC, בגילוי אוטומטי או באימות פרוקסי. צריך קודם לאשר איזה מחסנית HTTP האפליקציה היעד משתמשת ומאיזו משפחת תצורה היא פותרת את הפרוקסי.
- אילו הגדרות פרוקסי קוראת אפליקציית .NET?
- .NET Framework משתמש כברירת מחדל בהגדרות אפשרויות האינטרנט (מקבילת WinINET) של חשבון ההרצה, וניתן לדרוס אותן באלמנט system.net/defaultProxy ב-app.config. HttpClient ב-.NET (Core ואילך) קורא תחילה משתני סביבה כמו HTTP_PROXY, HTTPS_PROXY ו-NO_PROXY, ואם אינם מוגדרים נופל להגדרות פרוקסי המשתמש של Windows. בשני המקרים HttpClientHandler.Proxy מפורש הוא בעדיפות. סדר הפתרון כברירת מחדל שונה אפוא בין Framework לבין Core ואילך, ולכן צריך לבדוק מחדש את התנהגות הפרוקסי במעבר.
- מה לבדוק כאשר מוחזר 407 Proxy Authentication Required?
- 407 הוא סימן שהפרוקסי עצמו דורש אימות; זה דבר אחר משגיאת אימות של שרת היעד (401). אשרו תחילה את סכמת האימות שהפרוקסי מבקש (Negotiate, NTLM, Basic) מכותרת Proxy-Authenticate, וב-.NET העבירו אישורים עם HttpClientHandler.DefaultProxyCredentials או WebProxy.UseDefaultCredentials. באפליקציה שרצה תחת חשבון שירות, «אישורי ברירת המחדל» הופכים לאלו של חשבון השירות, ולכן התקרית הטיפוסית היא שעובד למשתמש אינטראקטיבי ואז 407 ברגע שהופכים לשירות. בדקו גם ביומן צד הפרוקסי כמי הוא אימת.
- פרוקסי בדיקת TLS מייצר שגיאות אישור. מותר לבטל את אימות האישורים?
- ביטול אינו מומלץ. פרוקסי בדיקת TLS מפענח את התעבורה ואז מציג ללקוח אישור שנחתם מחדש על ידי רשות האישורים שלו, כך שהאימות נכשל אם אישור רשות זה אינו בשורשים המהימנים. התיקון הנכון הוא להפיץ את אישור רשות האישורים הפנימית למאגר האישורים של Windows (בדרך כלל רשויות אישורים שורשיות מהימנות של המחשב המקומי). ביטול האימות בקוד פירושו שמתקפת איש-באמצע לא תתגלה כאשר האפליקציה בשימוש ברשת חיצונית, והפגיעות נשארת.