«Trình duyệt mở được trang ngoài, nhưng chỉ ứng dụng nghiệp vụ không tới API ngoài.» «Chạy trên máy phát triển, nhưng hết thời gian trên mạng khách.» «Giao tiếp khi tôi chạy tay, và thất bại ngay khi biến thành dịch vụ Windows.» — Khi bạn chạy ứng dụng nghiệp vụ trong môi trường có proxy doanh nghiệp, kiểu tư vấn này thuộc hàng phổ biến nhất.
Phần lớn trường hợp nguyên nhân không phải sự cố máy chủ proxy cũng không phải lỗi ứng dụng. Windows có vài họ riêng biệt của thứ người ta gọi là «thiết lập proxy», và thiết lập nào ai đọc khác nhau theo ứng dụng (theo ngăn xếp HTTP nó dùng) và theo tài khoản chạy — sự lệch đó. Thiết lập trình duyệt đọc, thiết lập dịch vụ đọc, và thiết lập HttpClient .NET đọc mỗi thứ có thể là một thứ khác. Một khi cấu trúc đó vào đầu, cô lập «chạy được trên trình duyệt, nhưng…» trở nên nhanh đáng ngạc nhiên.
Bài viết hướng tới nhân viên CNTT doanh nghiệp vừa và nhỏ và lập trình viên ứng dụng Windows. Nó nối, trong một bức tranh, ba họ thiết lập proxy — WinINET, WinHTTP và biến môi trường — cấu hình tự động PAC và WPAD, khác biệt phân giải proxy giữa .NET Framework và .NET (Core trở đi), proxy xác thực (407), kiểm tra TLS, và quy trình cô lập thực tế. Mẫu tạo HttpClient và thiết kế thời gian chờ tự thân được trình bày trong «Đừng bọc HttpClient trong using», nên bài này tập trung vào phân giải proxy.
1. Kết luận trước
- Thiết lập proxy Windows không phải một thứ; có ít nhất ba họ. (1) Thiết lập WinINET theo người dùng (trang «Proxy» trong ứng dụng Cài đặt = Tùy chọn Internet cũ), (2) thiết lập máy WinHTTP (
netsh winhttp), và (3) biến môi trườngHTTP_PROXY/HTTPS_PROXY. Cái nào được đọc do phía ứng dụng quyết định.12 - «Proxy» bạn thấy trong ứng dụng Cài đặt là thiết lập theo người dùng của WinINET. Trình duyệt và ứng dụng tương tác đọc chúng; dịch vụ Windows thì không. WinINET không được hỗ trợ dùng trong dịch vụ; việc dùng dịch vụ là việc của WinHTTP.13
- Nguyên nhân phổ biến nhất của «chạy tay được nhưng không chạy như dịch vụ» là khác tài khoản chạy. LocalSystem và tài khoản dịch vụ không thấy proxy theo người dùng mà quản trị viên đã cấu hình trên màn hình của mình.34
netsh winhttp set proxylà thiết lập tĩnh; không xử lý PAC, phát hiện tự động hay xác thực proxy. Nếu muốn cấu hình PAC hoặc WPAD theo máy, cần phíanetsh winhttp set advproxy.42- Kết quả PAC đổi theo URL. Hàm
FindProxyForURLcủa tệp PAC nhận URL và máy chủ rồi trả danh sách proxy hoặc kết nối trực tiếp (DIRECT). «Trang kia chạy, chỉ API này không» có thể là nhánh PAC.56 - HttpClient trên .NET (Core trở đi) khởi tạo proxy mặc định theo thứ tự biến môi trường → thiết lập proxy người dùng Windows. Nếu bất kỳ trong
HTTP_PROXY,HTTPS_PROXYhoặcALL_PROXYđược định nghĩa, nó ưu tiên hơn thiết lập hệ điều hành, nên tai nạn «ai đó để lại biến môi trường» có thể xảy ra.7 - Mặc định của .NET Framework là Tùy chọn Internet của tài khoản đang chạy, và có thể ghi đè bằng
defaultProxytrong app.config. Thiết lập tệp cấu hình ưu tiên hơn thiết lập hệ thống.89 - 407 là lỗi xác thực proxy; khác với 401 (xác thực máy chủ). Lược đồ gồm Negotiate, NTLM và Basic, và trong .NET bạn truyền thông tin xác thực bằng
DefaultProxyCredentialshoặcWebProxy.UseDefaultCredentials. Chú ý rằng dưới tài khoản dịch vụ nội dung «thông tin xác thực mặc định» đổi.101112 - Proxy kiểm tra TLS chỉ đứng vững khi đi cùng phân phối chứng chỉ CA nội bộ. Máy và thời gian chạy chưa nhận được sẽ gặp lỗi xác thực chứng chỉ. Giải bằng phân phối vào kho chứng chỉ, không phải tắt xác thực trong ứng dụng.134
Một câu: mỗi lần nói «tôi đã kiểm tra thiết lập proxy», luôn phải nói được đã kiểm tra họ nào trong ba họ, và từ tài khoản nào — đó là chủ đề bài viết.
2. Windows có ba họ «thiết lập proxy»
Trước hết, bản đồ tổng thể. Các đường ứng dụng Windows dùng để tìm proxy doanh nghiệp rơi vào ba họ này.
| Họ thiết lập | Nơi đặt / lệnh | Phạm vi | Ai chủ yếu đọc |
|---|---|---|---|
| (1) WinINET (Tùy chọn Internet) | Cài đặt → Mạng & Internet → Proxy, inetcpl.cpl |
Theo người dùng (mặc định) | Trình duyệt, ứng dụng máy tính tương tác, mặc định .NET Framework |
| (2) WinHTTP (thiết lập máy) | netsh winhttp set proxy / set advproxy |
Máy | Dịch vụ Windows, một số thành phần hệ điều hành |
| (3) Biến môi trường | HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY |
Tiến trình (kế thừa tùy nơi định nghĩa) | HttpClient trên .NET (Core trở đi), curl, công cụ đa nền tảng như Node.js và Python |
(1) là thứ người ta thường nhận là «thiết lập proxy Windows»; bản chất là cấu hình WinINET. Lịch sử là Tùy chọn Internet của Internet Explorer, và mặc định lưu theo người dùng.4
(2) là mặc định theo máy cho ngữ cảnh như dịch vụ nơi «không có người dùng đã đăng nhập». (3) chủ yếu là quy ước của công cụ đến từ thế giới đa nền tảng; trên Windows, .NET (Core trở đi) và curl cũng đọc.7
Điểm quan trọng là họ nào được đọc do phía ứng dụng quyết định, không phải phía thiết lập. Nếu ứng dụng dùng WinINET bên trong thì đọc (1); nếu WinHTTP thì (2) (hoặc ghi đè riêng ứng dụng); nếu .NET (Core trở đi) thì (3) rồi (1). Vậy thường không phải «thiết lập proxy đúng nhưng vẫn không kết nối»; thực tế là «họ ứng dụng đang đọc là họ khác với họ bạn đã kiểm tra».
flowchart TB
accTitle: Ba họ thiết lập proxy Windows
accDescr: WinINET là Cài đặt và Tùy chọn Internet theo người dùng, WinHTTP là mặc định máy qua netsh, và biến môi trường có phạm vi tiến trình. Họ nào được đọc do ứng dụng quyết định, không phải phía thiết lập
fam{"Họ nào?"}
fam --> wininet["Thiết lập WinINET theo người dùng"]
fam --> winhttp["Thiết lập máy WinHTTP"]
fam --> env["HTTP_PROXY và bạn bè"]
wininet -.-> r1["Trình duyệt và ứng dụng máy tính"]
winhttp -.-> r2["Dịch vụ và một phần hệ điều hành"]
env -.-> r3[".NET Core+ và curl"]
Hình 1: Ba họ nằm cạnh nhau. Ứng dụng chọn cái nào để đọc.
Nếu bật Chính sách nhóm «Làm thiết lập proxy theo máy (thay vì theo người dùng)», có thể chuyển (1) sang theo máy và áp dụng cùng thiết lập cho mọi người dùng. Với MDM (Intune và tương tự) có thể cấu hình theo thiết bị bằng NetworkProxy CSP.4
3. WinINET và WinHTTP — cho ứng dụng tương tác và cho dịch vụ
3.1. Khác biệt vai trò
WinINET và WinHTTP đều là ngăn xếp máy khách HTTP inbox của Windows, nhưng giả định cách dùng khác nhau.
- WinINET: hướng tới ứng dụng máy tính tương tác. Tự động kế thừa Tùy chọn Internet của người dùng (proxy, cookie, bộ nhớ thông tin xác thực) và thậm chí có thể hiện giao diện nhập thông tin xác thực nếu cần. Dùng trong dịch vụ hoặc tiến trình giống dịch vụ không được hỗ trợ.1
- WinHTTP: hướng tới dịch vụ và phía máy chủ. Hỗ trợ chạy dưới tài khoản dịch vụ, mạo danh luồng và cô lập phiên; đổi lại không chia sẻ thiết lập trình duyệt, cookie hay thông tin xác thực của người dùng. Cũng không hiện giao diện.3
Hướng dẫn của chính Microsoft cũng rõ: «dùng WinINET trừ khi bạn chạy trong dịch vụ, hoặc trong tiến trình giống dịch vụ cần cô lập phiên và mạo danh» — nói ngược lại, nếu là dịch vụ thì dùng WinHTTP.1
flowchart TB
accTitle: WinINET cho ứng dụng tương tác, WinHTTP cho dịch vụ
accDescr: WinINET kế thừa Tùy chọn Internet của người dùng đã đăng nhập và không được hỗ trợ trong dịch vụ. WinHTTP chạy dưới tài khoản dịch vụ không giao diện và không chia sẻ thiết lập trình duyệt của người dùng
q{"Ứng dụng máy tính tương tác?"}
q -->|"Có"| ie["WinINET"]
q -->|"Dịch vụ hoặc giống dịch vụ"| wh["WinHTTP"]
ie -.-> ieNote["Đọc Tùy chọn Internet của người dùng"]
wh -.-> whNote["Thiết lập máy, không giao diện"]
Hình 2: Ứng dụng tương tác dùng WinINET. Dịch vụ dùng WinHTTP.
3.2. Thao tác netsh winhttp cơ bản
Proxy mặc định máy của WinHTTP được vận hành bằng 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
Hai ràng buộc cần nhớ ở đây.
netsh winhttp set proxylà thiết lập tĩnh. Không xử lý phát hiện proxy tự động, cũng không chỉ định URL PAC, cũng không xác thực proxy.4import proxy source=iechỉ sao chép thiết lập tĩnh tại thời điểm đó; không theo thay đổi sau ở phía Tùy chọn Internet. Khi cần cấu hình theo máy gồm PAC hoặc phát hiện tự động, cấu hình thiết lập chi tiết dạng JSON (Proxy,ProxyBypass,AutoconfigUrl,AutoDetect) bằngnetsh winhttp set advproxy.2
3.3. Cạm bẫy phổ biến nhất: dịch vụ không đọc thiết lập IE của người dùng
Mẫu thấy nhiều nhất tại hiện trường, theo thứ tự thời gian, trông như sau.
- Lập trình viên chạy công cụ trên máy mình → thiết lập proxy theo người dùng (1) có hiệu lực và chạy được
- Trên sản xuất để thường trú như dịch vụ Windows (Cách xây dựng và vận hành dịch vụ Windows) dưới LocalSystem
- Thiết lập nhìn thấy từ LocalSystem là thứ khác (thiết lập theo người dùng không thấy, thiết lập máy WinHTTP chưa cấu hình = DIRECT) → thử kết nối trực tiếp tới API ngoài và hết thời gian
Không phải «không chạy dù cùng máy»; cùng máy nhưng tài khoản chạy khác nghĩa là tập thiết lập proxy nhìn thấy khác. Với tiến trình giao tiếp ngay cả khi không có người dùng đăng nhập, cách đúng là chuẩn bị thiết lập theo máy ở dạng ngăn xếp HTTP của tiến trình đó thực sự đọc. Với ứng dụng gốc hoặc thành phần Windows dùng WinHTTP, thiết lập WinHTTP của netsh có hiệu lực.4 HttpClient trên .NET (Core trở đi) thì không đọc thiết lập máy WinHTTP (xem Chương 5), nên với dịch vụ .NET bạn đặt biến môi trường hệ thống (HTTPS_PROXY và tương tự) hoặc chỉ định HttpClientHandler.Proxy tường minh từ thiết lập ứng dụng.
Tai nạn cũng xảy ra chiều kia. Nếu nướng proxy tĩnh vào máy xách tay đi giữa mạng doanh nghiệp và bên ngoài bằng netsh winhttp set proxy, proxy đó không tới được ngoài công ty và giao tiếp chết hoàn toàn. Coi thiết lập tĩnh máy là phương tiện hướng tới máy chủ mà cấu hình mạng không đổi.4
flowchart TB
accTitle: Vì sao dịch vụ không thấy thiết lập IE của người dùng
accDescr: Chạy của lập trình viên đọc thiết lập WinINET theo người dùng và thành công. Là LocalSystem những thiết lập đó không thấy. Ứng dụng WinHTTP gốc rồi theo thiết lập máy chưa cấu hình (DIRECT). Dịch vụ .NET Core+ vẫn dùng biến môi trường hoặc handler.Proxy tường minh và không chuyển sang netsh winhttp
dev["Chạy tay với tư cách người dùng"] --> ok["Thiết lập WinINET theo người dùng áp dụng"]
svc["Dịch vụ Windows là LocalSystem"] --> miss["Thiết lập theo người dùng không thấy"]
miss --> stack{"Ngăn xếp HTTP nào?"}
stack -->|"WinHTTP"| direct["WinHTTP chưa cấu hình = DIRECT"]
stack -->|".NET Core+"| env["Biến môi trường hoặc handler.Proxy"]
direct --> fail["API ngoài hết thời gian"]
Hình 3: Cùng máy, tài khoản khác, tập thiết lập proxy nhìn thấy khác.
4. PAC và WPAD — «cấu hình tự động» thực sự là gì
4.1. Tệp PAC và FindProxyForURL
Tệp PAC (Proxy Auto-Configuration) là JavaScript (ECMAScript) tính «proxy nào dùng cho URL này», và luôn chứa hàm tên FindProxyForURL(url, host). Hàm trả danh sách proxy nên dùng, hoặc giá trị trả đặc biệt (DIRECT) nghĩa là được kết nối trực tiếp không qua proxy.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";
}
Hai hệ quả thực tế theo sau.
- Phân giải proxy phải làm theo URL. Vì PAC có thể trả proxy khác hoặc kết nối trực tiếp tùy URL (máy chủ), tính năng proxy tự động của WinHTTP cũng được thiết kế để truyền URL yêu cầu và truy vấn mỗi lần.6 «Trình duyệt thấy trang khác» không chứng minh API có vấn đề đi cùng đường.
- DIRECT là chỉ thị «đi không qua proxy». Nếu lưu lượng lẽ ra nội bộ không bao giờ xuất hiện trong nhật ký proxy, trước hết nghi PAC đã trả DIRECT (hoặc khớp danh sách bỏ qua).
4.2. Phát hiện tự động qua WPAD
Bật «Tự động phát hiện cài đặt» thì máy tìm vị trí tệp PAC bằng giao thức WPAD (Web Proxy Auto-Discovery). Trong cấu hình điển hình, DHCP đưa URL PAC, hoặc DNS được dùng để tra máy chủ tên wpad và PAC được tải từ URL như http://wpad/wpad.dat.14
Nói cách khác, «phát hiện tự động» không phải phép thuật; đó là cơ chế chỉ hoạt động trên mạng đã sắp xếp WPAD trong DHCP/DNS. Chỉ bật phát hiện tự động trên mạng không có sắp xếp đó chỉ thêm thời gian chờ thất bại phát hiện.
flowchart TB
accTitle: PAC phân giải proxy theo URL, WPAD chỉ tìm PAC
accDescr: FindProxyForURL nhận URL và máy chủ rồi trả danh sách proxy hoặc DIRECT. WPAD chỉ định vị PAC qua DHCP hoặc DNS. Máy khách không đánh giá được PAC rơi về proxy tĩnh hoặc biến môi trường
url["URL yêu cầu"] --> pac["FindProxyForURL"]
pac -->|"danh sách proxy"| via["Đi qua proxy"]
pac -->|"DIRECT"| dir["Kết nối không qua proxy"]
wpad["WPAD qua DHCP hoặc DNS"] -.-> pac
nopac["Máy khách không đánh giá PAC"] -.-> fb["Thiết lập tĩnh hoặc biến môi trường"]
Hình 4: PAC quyết định theo URL. WPAD chỉ tìm tệp PAC.
4.3. Máy khách không đánh giá được PAC hành xử thế nào
Không phải mọi máy khách đều đánh giá được PAC.
- Thiết lập tĩnh của
netsh winhttp set proxykhông đánh giá PAC.4 - Công cụ dùng kiểu biến môi trường
HTTP_PROXYtheo quy tắc chỉ viết được URL proxy cố định (không chỗ viết URL PAC).7 - Với ứng dụng gốc dùng WinHTTP trực tiếp, tùy cách mở phiên. Ứng dụng mở bằng
WinHttpOpentrên Windows 8.1 trở đi chỉ địnhWINHTTP_ACCESS_TYPE_AUTOMATIC_PROXYkhiến WinHTTP tự phân giải thiết lập proxy hệ thống/người dùng (gồm WPAD/PAC) theo từng yêu cầu.15 Nếu mở bằngWINHTTP_ACCESS_TYPE_DEFAULT_PROXYcũ hơn (không dùng từ 8.1) hoặc tương tự, proxy tự động không được tích hợp vào ngăn xếp HTTP, và ứng dụng phải tự gọiWinHttpGetProxyForUrlrồi áp kết quả vào yêu cầu. Nói cách khác, trên triển khai cũ hơn, PAC có thể có mà vẫn không được dùng.5
«Trình duyệt đi đúng proxy qua PAC, nhưng ứng dụng nghiệp vụ không đọc PAC và thử kết nối trực tiếp rồi thất bại» — đây là lệch cổ điển khác. Trên mạng vận hành PAC cần quyết định dự phòng — thiết lập tĩnh hoặc biến môi trường — cho máy khách không đọc được PAC.
5. Phân giải proxy .NET — Framework và Core trở đi là hai thứ khác nhau
Thiết lập proxy ứng dụng .NET đọc khác nhau theo mặc định giữa .NET Framework và .NET (Core trở đi). Nhầm hai thứ thì sẽ điều tra ứng dụng .NET 8 bằng kiến thức thời Framework và bỏ sót.
5.1. .NET Framework — mặc định là Tùy chọn Internet, ghi đè bằng defaultProxy
Trên .NET Framework, HttpWebRequest và HttpClient ngồi trên nó dùng proxy mặc định trừ khi bạn chỉ định Proxy tường minh. Proxy mặc định được quyết định bởi tổ hợp thiết lập Internet hệ thống (thiết lập WinINET của tài khoản đang chạy) và tệp cấu hình, và thiết lập tệp cấu hình được ưu tiên.8
Bạn có thể điều khiển mặc định này bằng phần tử system.net/defaultProxy trong app.config (hoặc 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>
Để phần tử defaultProxy trống thì dùng thiết lập hệ thống (Tùy chọn Internet); viết proxyaddress và tương tự thì những cái đó được ưu tiên. Từ chương trình có thể thay cùng mặc định bằng WebRequest.DefaultWebProxy.98
Cạm bẫy Chương 3.3 cũng áp dụng ở đây. Vì mặc định là «Tùy chọn Internet của tài khoản đang chạy», ứng dụng .NET Framework chạy dưới tài khoản dịch vụ đọc tập thiết lập khác (thường trống) với những gì nhìn thấy trên máy tính quản trị.
5.2. .NET (Core trở đi) — biến môi trường trước, rồi thiết lập người dùng hệ điều hành
HttpClient trên .NET (Core trở đi) có thuộc tính tĩnh HttpClient.DefaultProxy. Trừ khi handler chỉ định proxy tường minh, mọi thể hiện HttpClient dùng nó. Quy tắc khởi tạo trên Windows là «đọc biến môi trường, và nếu không được định nghĩa thì đọc thiết lập proxy người dùng».7
Các biến môi trường dùng như sau.7
| Biến môi trường | Ý nghĩa |
|---|---|
HTTP_PROXY |
Proxy dùng cho yêu cầu HTTP |
HTTPS_PROXY |
Proxy dùng cho yêu cầu HTTPS |
ALL_PROXY |
Dự phòng khi các biến trên không được định nghĩa |
NO_PROXY |
Danh sách máy chủ cách nhau bằng dấu phẩy không nên dùng proxy |
Ba điều cần chú ý.
- Nếu bất kỳ trong
HTTP_PROXY,HTTPS_PROXYhoặcALL_PROXYđược định nghĩa, nó ưu tiên hơn thiết lập proxy phía hệ điều hành. Chỉ định nghĩaNO_PROXYkhông cấu hình proxy từ biến môi trường, và trên Windows vẫn dùng thiết lập proxy người dùng hệ điều hành. «Thiết lập vô hình» như đểHTTPS_PROXYlàm biến môi trường hệ thống sau thí nghiệm cũ, hoặc mẫu CI/CD tiêm nó, là ổ tai nạn. NO_PROXYkhông hỗ trợ ký tự đại diện (*). Để khớp tên miền phụ, đặt dấu chấm đầu (.example.comkhớpwww.example.comnhưng không khớp chínhexample.com).7- Ngoài Windows (container Linux và tương tự), nếu biến môi trường không được định nghĩa thì khởi tạo không proxy. Hành vi mặc định của cùng ứng dụng đổi giữa Windows và Linux là điều cần xác nhận khi di chuyển container.7
5.3. Chỉ định tường minh — HttpClientHandler.Proxy và UseProxy
Trên mọi thời gian chạy, ưu tiên cao nhất là chỉ định tường minh trên handler. Chỉ định HttpClientHandler.Proxy ưu tiên hơn thiết lập hệ điều hành và tệp cấu hình, và UseProxy = false không dùng proxy chút nào.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);
Khi không có chỉ định tường minh và theo thiết lập hệ điều hành, bỏ qua tự động đích cục bộ có quy tắc. Tên phẳng không dấu chấm, địa chỉ loopback, đích khớp hậu tố miền của chính máy, và tương tự có thể được coi là «cục bộ».14 Hiện tượng như «hành vi đổi nếu tôi chỉ định địa chỉ IP» hoặc «bỗng nhiên bắt đầu đi qua proxy khi dùng FQDN» có thể do phán đoán này.
Thứ tự ưu tiên như sau.
| Ưu tiên (cao → thấp) | .NET Framework | .NET (Core trở đi) |
|---|---|---|
| 1 | Chỉ định tường minh như HttpClientHandler.Proxy |
Giống |
| 2 | defaultProxy trong app.config |
Gán cho HttpClient.DefaultProxy |
| 3 | Tùy chọn Internet của tài khoản đang chạy | Biến môi trường (HTTP_PROXY và khác) |
| 4 | — | Thiết lập proxy người dùng Windows |
flowchart TB
accTitle: Phân giải proxy mặc định ở Framework so với Core trở đi
accDescr: HttpClientHandler.Proxy tường minh luôn thắng. Framework rồi dùng app.config defaultProxy và Tùy chọn Internet của tài khoản đang chạy. Core trở đi dùng gán cho HttpClient.DefaultProxy, rồi biến môi trường, rồi thiết lập proxy người dùng Windows
expl["handler.Proxy tường minh"] --> done["Proxy đó được dùng"]
noexpl["Không có Proxy tường minh"] --> fw{"Thời gian chạy nào?"}
fw -->|"Framework"| cfg["app.config defaultProxy"]
cfg --> ie["Tùy chọn Internet tài khoản đang chạy"]
fw -->|"Core trở đi"| dp["HttpClient.DefaultProxy"]
dp --> ev["HTTP_PROXY và bạn bè"]
ev --> user["Thiết lập proxy người dùng Windows"]
Hình 5: Chỉ định tường minh luôn thắng. Đường mặc định khác theo thời gian chạy.
6. Proxy xác thực — 407 là lỗi xác thực của proxy
6.1. Đừng nhầm 407 với 401
Khi bạn cố đi qua proxy đòi xác thực, proxy trả mã trạng thái 407 (Proxy Authentication Required) và header Proxy-Authenticate liệt kê các lược đồ sẵn có. Đó khác với đòi xác thực của máy chủ đích (401 và WWW-Authenticate); bên bạn giao thông tin xác thực và chỗ bạn cấu hình chúng đều khác.10
flowchart TB
accTitle: 407 là proxy, 401 là máy chủ đích
accDescr: 407 và Proxy-Authenticate đến từ proxy. 401 và WWW-Authenticate đến từ máy chủ đích. Thông tin xác thực và chỗ cấu hình khác nhau
req["Yêu cầu đi ra"] --> who{"Ai đòi xác thực?"}
who -->|"Proxy"| e407["407 + Proxy-Authenticate"]
who -->|"Đích"| e401["401 + WWW-Authenticate"]
e407 -.-> cred["DefaultProxyCredentials"]
Hình 6: 407 là xác thực proxy. 401 là xác thực máy chủ.
Lược đồ gồm Basic, gửi tên người dùng và mật khẩu nguyên, và lược đồ thách thức/đáp như Negotiate (Kerberos/NTLM). Trong lược đồ thách thức/đáp mật khẩu không đi trên mạng, và xác thực hoàn tất qua vài lần trao đổi.10 Cơ chế lược đồ nó «rơi» xuống được trình bày kỹ hơn trong «NTLM và Kerberos giải thích bằng sơ đồ».
6.2. Cách truyền thông tin xác thực trong .NET
Khi muốn dùng proxy mặc định từ thiết lập hệ điều hành và chỉ cho xác thực qua, dùng HttpClientHandler.DefaultProxyCredentials. Đó là thông tin xác thực gửi tới proxy mặc định đó khi UseProxy = true và Proxy = null (= proxy mặc định hệ thống).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);
Khi chỉ định proxy tường minh, đặt thông tin xác thực ở phía WebProxy. Trong nhiều kịch bản máy khách khuyến nghị dùng thông tin xác thực mặc định của người dùng đã đăng nhập chứ không phải tên và mật khẩu riêng, và WebProxy.UseDefaultCredentials = true chính là điều đó.12
6.3. Vấn đề 407 của tài khoản dịch vụ
Tài khoản chạy cũng quan trọng ở đây. «Thông tin xác thực mặc định» nghĩa là thông tin xác thực của tài khoản đang chạy tiến trình đó. Chạy như người dùng tương tác thì xác thực với proxy là với tư cách người dùng đó; chạy như dịch vụ LocalSystem thì là tài khoản máy.
- Nếu proxy xác thực người dùng qua Active Directory, nó không xác thực được tài khoản máy hoặc tài khoản cục bộ, và 407 tiếp tục ngay khi biến ứng dụng thành dịch vụ
- Ngược lại, một số môi trường có miễn xác thực phía proxy cho dịch vụ (theo IP nguồn hoặc theo tài khoản)
Vậy điều tra 407 không khép lại chỉ ở «thiết lập ứng dụng»; đó là bộ với kiểm tra thiết kế phía hạ tầng: proxy có xác thực được tài khoản chạy không. Với ứng dụng sẽ biến thành dịch vụ, lúc thiết kế nên quyết định một trong: chạy dưới tài khoản dịch vụ miền (gMSA và tương tự), đặt miễn xác thực phía proxy, hoặc dựng proxy chuyển tiếp nội bộ không yêu cầu xác thực.
Cũng có kiểu nhúng thông tin xác thực vào biến môi trường, như HTTP_PROXY=http://user:pass@proxy:80807, nhưng mật khẩu văn bản rõ khi đó lộ trong biến môi trường (= thông tin tiến trình), nên không nên dùng cho vận hành thường xuyên.
7. HTTPS và proxy — đường hầm CONNECT và kiểm tra TLS
7.1. HTTPS đi qua proxy như một «đường hầm»
Khi dùng proxy cho HTTPS, máy khách trước hết gửi proxy yêu cầu CONNECT destination-host:443, và proxy mở đường hầm TCP. Thành công thì proxy trả 200, rồi máy khách và máy chủ đích thực hiện bắt tay TLS trong đường hầm đó. Nếu đường hầm không mở, proxy trả 407 (cần xác thực), 502 hoặc tương tự.16
Trong mô hình này proxy không đọc được nội dung đường hầm (HTTPS đã mã hóa). Thứ còn trong nhật ký proxy là tên máy chủ đích và kết nối có thành công; đường URL không thấy — đó là hành vi proxy «đi xuyên».
flowchart TB
accTitle: HTTPS qua proxy là đường hầm CONNECT
accDescr: Máy khách gửi CONNECT tới proxy, proxy mở đường hầm TCP và trả 200, rồi máy khách và đích bắt tay TLS trong đường hầm. Nhật ký proxy thấy máy chủ, không thấy đường URL
cli["Máy khách"] -->|"CONNECT host:443"| px["Proxy"]
px -->|"200 và đường hầm TCP"| dest["Đích"]
dest -->|"TLS trong đường hầm"| cli
px -.-> log["Nhật ký: chỉ máy chủ và thành công"]
Hình 7: Proxy đi xuyên thấy máy chủ, không thấy đường đã mã hóa.
7.2. Proxy kiểm tra TLS và lỗi chứng chỉ
Proxy sản phẩm bảo mật, mặt khác, gồm loại kiểm tra TLS (giải mã SSL, ngắt và kiểm tra) kết thúc TLS, kiểm tra nội dung, rồi mã hóa lại trước khi chuyển tiếp. Trong lược đồ này chứng chỉ máy chủ trình cho máy khách không phải cái thật; bị thay bằng chứng chỉ được CA của proxy ký lại.13
Tiền đề khiến cấu hình này đứng vững vì vậy là «chứng chỉ CA của proxy đã được phân phối tới gốc tin cậy của mọi máy khách». Trên máy chưa nhận, hoặc trong thời gian chạy không nhìn kho chứng chỉ Windows (công cụ có kho tin cậy riêng), bạn gặp lỗi xác thực chứng chỉ. Trong .NET thường lộ ra dưới dạng HttpRequestException bọc AuthenticationException (thông báo kiểu «the remote certificate is invalid»).
Nguyên tắc sửa như sau.
- Phân phối chứng chỉ CA nội bộ vào kho «Nhà cung cấp chứng chỉ gốc tin cậy» của máy tính cục bộ. Tách kho người dùng và kho máy được trình bày trong «Kho chứng chỉ Windows trong thực tế».
- Đừng tắt xác thực chứng chỉ trong mã. Cách vòng luôn trả true từ
ServerCertificateCustomValidationCallbacktrở thành ứng dụng dễ tổn thương không phát hiện người đứng giữa ngay khi ra mạng ngoài. - Lưu lượng ghim chứng chỉ vốn không kiểm tra được. Kết nối xác minh chứng chỉ Microsoft cụ thể, như một số thành phần Windows làm, thất bại ngay khi proxy đổi chứng chỉ, và không có cách nào khác ngoài loại trừ.4 Với lưu lượng tới SaaS như Microsoft 365, chính Microsoft khuyên loại trừ khỏi giải mã và kiểm tra lớp mạng.13
Triệu chứng «mọi trang nội bộ đều thấy, chỉ một dịch vụ đám mây cụ thể gây lỗi chứng chỉ trong ứng dụng» nên khiến bạn trước hết nghi kết hợp danh sách loại trừ kiểm tra TLS và ghim.
flowchart TB
accTitle: Proxy kiểm tra TLS ký lại chứng chỉ
accDescr: Proxy kết thúc TLS, kiểm tra nội dung, và trình chứng chỉ được CA của nó ký lại. Xác thực chỉ đứng khi CA đó nằm trong gốc tin cậy. Đừng tắt xác thực trong mã
real["Chứng chỉ máy chủ thật"] --> px["Proxy kiểm tra TLS"]
px --> fake["Được CA proxy ký lại"]
fake --> client["Xác thực máy khách"]
client -->|"CA trong gốc tin cậy"| ok["Thành công"]
client -->|"Thiếu CA"| err["Lỗi chứng chỉ"]
err -.-> fix["Phân phối CA vào kho"]
Hình 8: Kiểm tra chỉ hoạt động khi đi cùng phân phối CA nội bộ.
8. Quy trình cô lập — năm bước để xác định thủ phạm
Điều tra «không kết nối được» một cách máy móc theo thứ tự này.
| Bước | Bạn làm gì | Bạn học được gì |
|---|---|---|
| (1) Tái hiện | Truy cập URL có vấn đề bằng curl.exe -v hoặc Invoke-WebRequest (nên cùng máy, cùng tài khoản) |
Là vấn đề riêng ứng dụng hay vấn đề môi trường |
| (2) Thu thập thiết lập | Thu thập ba họ: netsh winhttp show proxy, thiết lập theo người dùng, và biến môi trường |
Có gì trong họ nào |
| (3) Xác định tài khoản | Xác định tài khoản chạy của ứng dụng đích (dịch vụ, Bộ lập lịch tác vụ, người dùng khác) | Nó chạy dưới thiết lập và thông tin xác thực nào |
| (4) Phân loại lỗi | Phân biệt 407 / 403 / thất bại phân giải tên / hết thời gian / lỗi chứng chỉ | Cô lập xác thực proxy, từ chối chính sách, đường đi, và kiểm tra TLS |
| (5) Nhật ký proxy | Kiểm tra thời điểm khớp trong nhật ký truy cập máy chủ proxy | Có tới proxy không, và xác thực với tư cách ai |
Bạn có thể thu thập (2) một lần bằng 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'
Vài mẹo thực tế.
- Trong thử tái hiện (1), ý thức công cụ đọc họ thiết lập nào.
curl.exeinbox Windows có thể chỉ định proxy tường minh bằng-x http://proxy:8080, và xác thực TLS thường dùng kho chứng chỉ hệ điều hành (Schannel).Invoke-WebRequestcủa Windows PowerShell 5.1 theo phía .NET Framework (Tùy chọn Internet mặc định); PowerShell 7 theo phía .NET (biến môi trường trước). «curl chạy được ứng dụng không» bản thân là gợi ý lệch giữa các họ cấu hình. - Nếu đích ở (3) là dịch vụ, kiểm tra lại (1) và (2) dưới cùng tài khoản với dịch vụ. Kiểm tra trong phiên của chính quản trị viên không chứng minh LocalSystem thấy gì.
- Trong phân loại lỗi (4), lấy Chương 6 (xác thực) làm ứng viên đầu cho 407, Chương 7 (kiểm tra TLS) cho lỗi chứng chỉ, và «không tới proxy» (đường, phân giải tên, tường lửa) cho hết thời gian. Mẫu nguyên nhân là quy tắc vào của Tường lửa Windows chứ không phải proxy được trình bày trong «Tường lửa Windows và ứng dụng nghiệp vụ».
- Nếu tới (5) mà nhật ký proxy vẫn không dấu vết, lưu lượng chưa bao giờ tới proxy. Nghi quyết định DIRECT của PAC, danh sách bỏ qua, hoặc biến môi trường còn sót, và nếu cần xác nhận đích thực bằng bắt gói («Bắt gói trên Windows trong thực tế — chọn giữa pktmon, netsh trace và Wireshark»).
flowchart TB
accTitle: Năm bước cô lập sự cố proxy
accDescr: Tái hiện dưới cùng tài khoản, thu thập ba họ thiết lập, xác định tài khoản chạy, phân loại lỗi, rồi kiểm tra nhật ký proxy
s1["Tái hiện bằng curl"] --> s2["Thu thập ba họ"]
s2 --> s3["Xác định tài khoản"]
s3 --> s4["Phân loại lỗi"]
s4 --> s5["Kiểm tra nhật ký proxy"]
s4 -.-> e407["407: xác thực"]
s4 -.-> ecert["Lỗi chứng chỉ: kiểm tra"]
s4 -.-> eto["Hết thời gian: chưa tới"]
Hình 9: Đi năm bước theo thứ tự. Lớp lỗi chọn chương tiếp.
9. Khuyến nghị thiết kế — làm ứng dụng «cấu hình được proxy»
Đảo quy trình điều tra thì thành hướng dẫn thiết kế phía ứng dụng. Với ứng dụng Windows sẽ giao vào môi trường có proxy doanh nghiệp, khuyến nghị như sau.
- Làm proxy cấu hình được từ thiết lập ứng dụng. Mặc định là «theo thiết lập hệ điều hành». Hầu hết môi trường mặc định đủ; chỉ ở môi trường ngoại lệ — không đọc được PAC, chạy như dịch vụ, cấu hình proxy đặc biệt — mới cho phép chỉ định URL proxy, danh sách bỏ qua, và «không dùng proxy» từ tệp thiết lập.
HttpClientHandler.Proxy/UseProxyở Mục 5.3 là điểm triển khai.14 - Viết cách đích nội bộ (API, cơ sở dữ liệu, máy chủ giấy phép, và tương tự) được xử lý như ngoại lệ proxy. Đặt dưới dạng có thể viết vào quy trình triển khai chúng bị loại trừ bởi PAC DIRECT, danh sách bỏ qua, hay
NO_PROXY. Quy tắc khớpNO_PROXY(không ký tự đại diện, dấu chấm đầu nghĩa là gì) bị hiểu sai rộng rãi, nên đính kèm ví dụ.7 - Thiết kế thời gian chờ và thử lại với giả định đi qua proxy. Nếu proxy chết hoặc kẹt xác thực, triển khai chờ thời gian mặc định dài đóng băng cả giao diện lẫn vận hành. Tách thời gian chờ kết nối ngắn hơn, và giới hạn thử lại ở yêu cầu lũy đẳng (chi tiết thiết kế trong «Đừng bọc HttpClient trong using»).
- Ghi nhật ký «proxy nào đã dùng». Làm chính ứng dụng trả lời được câu hỏi đầu của điều tra sự cố.
Nhật ký như (4) đã hiệu quả nếu chỉ ghi kết quả phân giải. Điểm là suy ra đường từ thiết lập (handler) bạn thực sự dùng để cấu hình máy khách. Nếu ghi trực tiếp HttpClient.DefaultProxy, bạn sẽ ghi giá trị lệch đường thực khi handler chỉ định Proxy tường minh hoặc đặt 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);
Nếu lúc khởi động ghi một lần «đường» và «tài khoản chạy» cho các đích chính, bước (1) đến (3) Chương 8 xong chỉ bằng đọc nhật ký. Khi được bảo «chạy được trên trình duyệt, nhưng…», nói được từ phía ứng dụng «tôi đã dùng thiết lập này, và đường này» là điều kiện của ứng dụng vững trước rắc rối proxy.
flowchart TB
accTitle: Làm proxy cấu hình được và ghi đường
accDescr: Mặc định theo thiết lập hệ điều hành, cho phép URL proxy tường minh hoặc bỏ qua hoặc không proxy từ thiết lập ứng dụng, và ghi tuyến thực sự dùng cùng tài khoản chạy
def["Mặc định: theo thiết lập hệ điều hành"] --> exc{"Môi trường ngoại lệ?"}
exc -->|"PAC chưa đọc / dịch vụ / đặc biệt"| cfg["Đặt URL, bỏ qua, hoặc không proxy"]
exc -->|"Trường hợp thường"| os["Dùng mặc định hệ điều hành"]
cfg --> log["Ghi tuyến và tài khoản"]
os --> log
Hình 10: Cấu hình khi phải. Luôn ghi đường nào đã dùng.
10. Tóm tắt
- Thiết lập proxy Windows tách thành ba họ — thiết lập WinINET theo người dùng, thiết lập máy WinHTTP, và biến môi trường — và cái nào được đọc do ứng dụng (ngăn xếp HTTP của nó) và tài khoản chạy quyết định.
- WinINET dành cho ứng dụng tương tác và không được hỗ trợ dùng trong dịch vụ; việc dùng dịch vụ là việc của WinHTTP (
netsh winhttp). Với «chạy tay được nhưng không chạy như dịch vụ», trước hết nghi khác tài khoản chạy. netsh winhttp set proxylà thiết lập tĩnh và không xử lý PAC, phát hiện tự động hay xác thực. Trên mạng vận hành PAC cần quyết định cách xử lý máy khách không đọc được PAC.FindProxyForURLcủa PAC trả proxy hoặc DIRECT theo URL. WPAD chỉ hoạt động trên mạng có sắp xếp DHCP/DNS.- Mặc định .NET Framework là Tùy chọn Internet của tài khoản đang chạy (ghi đè được bằng
defaultProxy); .NET (Core trở đi) là biến môi trường rồi thiết lập proxy người dùng. Chỉ định tường minh (HttpClientHandler.Proxy) luôn ưu tiên cao nhất. - 407 là lỗi xác thực proxy; trong ứng dụng chạy dưới tài khoản dịch vụ nguyên nhân điển hình là «thông tin xác thực mặc định» trở thành người khác.
- Proxy kiểm tra TLS giả định phân phối chứng chỉ CA nội bộ, và câu trả lời đúng cho lỗi chứng chỉ là phân phối vào kho chứng chỉ, không phải tắt xác thực. Lưu lượng đã ghim cần loại trừ.
- Cô lập máy móc theo thứ tự «tái hiện → thu thập ba họ thiết lập → xác định tài khoản chạy → phân loại lỗi → nhật ký proxy». Phía ứng dụng, thiết kế «cấu hình được proxy, và ghi đường đã dùng» là phòng ngừa tốt nhất.
Lần sau được tư vấn «chỉ ứng dụng nghiệp vụ không kết nối», hỏi điều này trước.
Ứng dụng đó chạy dưới tài khoản của ai, và đọc họ nào trong ba họ thiết lập proxy?
Một câu hỏi đó đổi cửa vào điều tra rất nhiều.
Bài viết liên quan
- Đừng bọc HttpClient trong using — giao tiếp HTTP thực tế trong ứng dụng nghiệp vụ C# (mẫu tạo, thời gian chờ, thử lại)
- Bắt gói trên Windows trong thực tế — chọn giữa pktmon, netsh trace và Wireshark
- Tường lửa Windows và ứng dụng nghiệp vụ — đăng ký quy tắc vào từ trình cài đặt
- Cách xây dựng và vận hành dịch vụ Windows — từ chọn giữa Bộ lập lịch tác vụ và dịch vụ đến biến BackgroundService thành dịch vụ Windows
- NTLM và Kerberos giải thích bằng sơ đồ — vì sao xác thực rơi về NTLM
- Kho chứng chỉ Windows trong thực tế — người dùng hay máy tính, nên dùng cái nào?
Lĩnh vực tư vấn liên quan
KomuraSoft LLC đảm nhận điều tra sự cố giao tiếp ứng dụng Windows trong môi trường proxy doanh nghiệp, proxy xác thực và kiểm tra TLS — «chạy trên máy phát triển nhưng không giao tiếp trên mạng khách», «sau khi biến thành dịch vụ không còn tới API ngoài» — và tư vấn thiết kế giao tiếp ứng dụng nghiệp vụ giả định môi trường proxy (mục thiết lập, thời gian chờ, thiết kế nhật ký). Có thể bắt đầu từ sắp xếp bước tái hiện và cách thu thập nhật ký.
- Phát triển ứng dụng Windows
- Điều tra lỗi và nguyên nhân
- Tư vấn kỹ thuật và đánh giá thiết kế
- Liên hệ với chúng tôi
Liên kết tham khảo
-
Microsoft Learn, WinINet vs. WinHTTP. Về hướng dẫn dùng WinINET trừ khi bạn ở dịch vụ hoặc tiến trình cần mạo danh và cô lập phiên, và về bảng so sánh tính năng gồm bộ nhớ thông tin xác thực, lời nhắc thông tin xác thực, hỗ trợ dịch vụ, mạo danh, cô lập phiên, và tương tự. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, netsh winhttp. Về cú pháp netsh winhttp show/set/import/reset; proxy-server và bypass-list của set proxy; import proxy source=ie; và thiết lập proxy chi tiết dạng JSON (Proxy, ProxyBypass, AutoconfigUrl, AutoDetect) qua set advproxy. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, About WinHTTP. Về WinHTTP là ngăn xếp HTTP thiết kế cho dùng dịch vụ và phía máy chủ, hỗ trợ chạy dưới tài khoản dịch vụ và mạo danh, và không chia sẻ cookie, bộ nhớ, thông tin xác thực của trình duyệt hay Tùy chọn Internet của người dùng. ↩ ↩2 ↩3
-
Microsoft Learn, Using a proxy with Delivery Optimization. Về netsh winhttp set proxy là thiết lập tĩnh không hỗ trợ phát hiện tự động, URL PAC hay xác thực proxy; cấu hình proxy theo thiết bị cho ngữ cảnh không có người dùng đăng nhập (NetworkProxy CSP, chính sách «Làm thiết lập proxy theo máy»); và lưu lượng ghim chứng chỉ thất bại dưới kiểm tra TLS và cần loại trừ. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, WinHTTP AutoProxy Support. Về tập lệnh PAC chứa hàm FindProxyForURL(url, host) tính danh sách proxy theo yêu cầu và chỉ kết nối trực tiếp bằng giá trị trả đặc biệt, và về API AutoProxy cũ hơn không tự tích hợp proxy tự động vào ngăn xếp HTTP nên ứng dụng phải gọi WinHttpGetProxyForUrl. ↩ ↩2 ↩3
-
Microsoft Learn, WinHttpGetProxyForUrl function. Về đó là triển khai giao thức WPAD, cần gọi theo URL vì tệp PAC có thể trả proxy khác theo URL, và hỗ trợ cả URL PAC tường minh lẫn phát hiện tự động từ mạng. ↩ ↩2
-
Microsoft Learn, HttpClient.DefaultProxy Property. Về Windows đọc biến môi trường HTTP_PROXY, HTTPS_PROXY, ALL_PROXY và NO_PROXY trước và, nếu không được định nghĩa, thiết lập proxy người dùng; Linux khởi tạo không proxy nếu thiếu biến môi trường; NO_PROXY không hỗ trợ ký tự đại diện và dùng khớp tên miền phụ dấu chấm đầu; và URL proxy có thể gồm tên người dùng và mật khẩu. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, Configuring Internet Applications. Về phần tử defaultProxy định nghĩa proxy mặc định trên .NET Framework; HttpWebRequest không có thuộc tính Proxy dùng proxy mặc định; và thiết lập Internet hệ thống cùng thiết lập tệp cấu hình được kết hợp với phía tệp cấu hình được ưu tiên. ↩ ↩2 ↩3
-
Microsoft Learn, defaultProxy element (network settings). Về thuộc tính enabled và useDefaultCredentials của phần tử system.net/defaultProxy, phần tử con proxy, bypasslist và module, thiết lập proxy hệ thống được dùng nếu phần tử trống, và cấu hình bằng HttpClient.DefaultProxy khi di chuyển sang .NET 6 trở đi. ↩ ↩2 ↩3
-
Microsoft Learn, Authentication in WinHTTP. Về mã trạng thái 407 và header Proxy-Authenticate được trả khi cần xác thực proxy (xác thực máy chủ là 401 và WWW-Authenticate); khác biệt giữa xác thực Basic và lược đồ thách thức/đáp như Kerberos; và lược đồ thách thức/đáp nghĩa là tên người dùng và mật khẩu không đi trên mạng. ↩ ↩2 ↩3
-
Microsoft Learn, HttpClientHandler.DefaultProxyCredentials Property. Về thuộc tính đặt thông tin xác thực dùng để xác thực với proxy mặc định khi UseProxy là true và Proxy là null để dùng proxy mặc định hệ thống. ↩ ↩2
-
Microsoft Learn, WebProxy.Credentials Property. Về thuộc tính Credentials là thông tin xác thực gửi tới proxy để đáp HTTP 407, và khuyến nghị trong nhiều kịch bản máy khách đặt UseDefaultCredentials thành true để dùng thông tin xác thực mặc định của người dùng đã đăng nhập. ↩ ↩2
-
Microsoft Learn, Understanding implications when using network intermediation to decrypt or manipulate Microsoft 365 traffic at the network layer. Về kiểm tra TLS (giải mã SSL) là cấu hình trong đó proxy hoặc tường lửa giải mã, kiểm tra và mã hóa lại TLS; có thể gây sự cố và suy giảm hiệu năng ở dịch vụ giả định TLS đầu-cuối; và khuyến nghị loại trừ lưu lượng tới Microsoft 365 khỏi giải mã và kiểm tra lớp mạng. ↩ ↩2 ↩3
-
Microsoft Learn, Make HTTP requests with the HttpClient class. Về hai phương pháp cấu hình HttpClient.DefaultProxy và HttpClientHandler.Proxy; chỉ định Proxy ưu tiên hơn tệp cấu hình và thiết lập máy tính cục bộ; cấu hình WPAD điển hình lấy tệp PAC (wpad.dat và tương tự) qua tên DNS wpad hoặc DHCP; và phán đoán bỏ qua đích cục bộ theo tên phẳng, loopback và khớp hậu tố miền. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WinHttpOpen function. Về ý nghĩa từng giá trị dwAccessType. WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY (Windows 8.1 trở đi) tự quyết định proxy từ thiết lập proxy hệ thống/người dùng và cũng tự xử lý chuyển khi lỗi và xác thực, và WINHTTP_ACCESS_TYPE_DEFAULT_PROXY không dùng từ 8.1. ↩
-
Microsoft Learn, Work with existing on-premises proxy servers. Về HTTPS đi ra được thiết lập bằng yêu cầu CONNECT tới proxy; thành công trả HTTP 200; và phản hồi như 407 (cần xác thực) hoặc 502 cho biết proxy không cho phép giao tiếp, nên nên tiến hành cô lập cùng nhóm phía proxy. ↩
Bài viết liên quan
Các bài viết gần đây có cùng thẻ để tìm hiểu sâu hơn những chủ đề lân cận.
Bắt gói tin trên Windows trong thực tế — chọn giữa pktmon, netsh trace và Wireshark
Sự cố chỉ để lại "timeout" trong nhật ký ứng dụng được điều tra một tầng sâu hơn bằng cách nhìn các gói tin thực sự đi trên dây. Ngay cả ...
Bên trong ảo hóa Windows (Phần 3) — Máy ảo khởi động trong vài giây: Vì sao WSL2, Windows Sandbox và container lại nhẹ
Vì sao WSL2 và Windows Sandbox khởi động trong vài giây và cảm giác nhẹ đến vậy? Bài viết này giải thích các cơ chế, từ ảnh cơ sở động và...
Bên trong ảo hóa Windows (Phần 2) — Bộ nhớ ngay cả kernel cũng không thấy: VBS, HVCI và Credential Guard
Khi cài sạch trên phần cứng tương thích, VBS được bật mặc định và dùng hypervisor cùng SLAT để tạo cô lập mạnh hơn kernel. Bài viết này g...
Bên trong ảo hóa Windows (Phần 1) — Windows của bạn thực sự chạy ở đâu? Hypervisor và phân vùng
Khi bạn bật Hyper-V, chính Windows máy chủ chạy trên hypervisor như phân vùng gốc. Bài viết này giải thích nền tảng ảo hóa qua vai trò củ...
API thread pool Win32 — Đồng thời mà không tạo luồng, với CreateThreadpoolWork
Bạn đang rải các lời gọi CreateThread khắp mã native? Bài viết này giải thích API thread pool Win32 được thiết kế lại từ Vista — bốn đối ...
Chủ đề liên quan
Các trang này đặt chủ đề trong bối cảnh rộng hơn của dịch vụ và quyết định.
Chủ đề kỹ thuật Windows
Cổng vào phát triển Windows, điều tra lỗi và khai thác tài sản hiện có.
Dịch vụ liên quan đến chủ đề này
Bài viết liên quan trực tiếp đến các dịch vụ sau.
Phát triển ứng dụng Windows
Ứng dụng nghiệp vụ, tích hợp thiết bị và công cụ liên lạc, từ yêu cầu đến phát triển.
Câu hỏi thường gặp
Các câu hỏi thường gặp khi tư vấn về chủ đề của bài viết.
- Trình duyệt kết nối được, nhưng chỉ ứng dụng nghiệp vụ không vượt proxy doanh nghiệp. Vì sao?
- Trình duyệt đọc thiết lập proxy theo người dùng của WinINET, nhưng ứng dụng nghiệp vụ không nhất thiết đọc cùng thiết lập. Ứng dụng chạy như dịch vụ Windows, hoặc dưới tài khoản khác, tham khảo thiết lập nhìn thấy từ tài khoản đó, thiết lập máy của WinHTTP, hoặc biến môi trường. Trước hết xác định tài khoản chạy, rồi kiểm tra thiết lập proxy nhìn thấy từ tài khoản đó cả bằng netsh winhttp show proxy lẫn trong thiết lập người dùng. Nếu tái hiện được bằng curl.exe hoặc tương tự dưới cùng tài khoản trên cùng máy, có thể coi là lệch giữa các họ cấu hình chứ không phải vấn đề riêng của ứng dụng.
- Tôi đã đặt netsh winhttp set proxy, nhưng lưu lượng ứng dụng không đổi. Vì sao?
- Điều netsh winhttp đặt là mặc định máy của WinHTTP. Nó không ảnh hưởng trình duyệt hay ứng dụng tương tác đọc WinINET, cũng không ảnh hưởng HttpClient của .NET (Core trở đi), vốn ưu tiên biến môi trường. netsh winhttp set proxy cũng là thiết lập tĩnh; không xử lý cấu hình tự động PAC, phát hiện tự động hay xác thực proxy. Trước hết cần xác nhận ứng dụng đích dùng ngăn xếp HTTP nào và phân giải proxy từ họ cấu hình nào.
- Ứng dụng .NET đọc những thiết lập proxy nào?
- .NET Framework mặc định dùng Tùy chọn Internet (tương đương WinINET) của tài khoản đang chạy, và có thể ghi đè bằng phần tử system.net/defaultProxy trong app.config. HttpClient trên .NET (Core trở đi) đọc biến môi trường như HTTP_PROXY, HTTPS_PROXY và NO_PROXY trước, và nếu không được định nghĩa thì rơi về thiết lập proxy người dùng Windows. Trong cả hai trường hợp, HttpClientHandler.Proxy tường minh được ưu tiên. Thứ tự phân giải mặc định khác nhau giữa Framework và Core trở đi, nên khi di chuyển cần kiểm tra lại hành vi proxy.
- Cần kiểm tra gì khi trả về 407 Proxy Authentication Required?
- 407 là dấu hiệu chính proxy đang đòi xác thực; khác với lỗi xác thực máy chủ đích (401). Trước hết xác nhận lược đồ proxy yêu cầu (Negotiate, NTLM, Basic) từ header Proxy-Authenticate, và trong .NET truyền thông tin xác thực bằng HttpClientHandler.DefaultProxyCredentials hoặc WebProxy.UseDefaultCredentials. Trong ứng dụng chạy dưới tài khoản dịch vụ, «thông tin xác thực mặc định» trở thành của tài khoản dịch vụ đó, nên sự cố điển hình là chạy được với người dùng tương tác rồi 407 ngay khi biến thành dịch vụ. Cũng kiểm tra nhật ký phía proxy xem nó xác thực với tư cách ai.
- Proxy kiểm tra TLS gây lỗi chứng chỉ. Có được tắt xác thực chứng chỉ không?
- Không nên tắt. Proxy kiểm tra TLS giải mã lưu lượng rồi trình cho máy khách chứng chỉ được CA của nó ký lại, nên xác thực thất bại nếu chứng chỉ CA đó không nằm trong gốc tin cậy. Cách sửa đúng là phân phối chứng chỉ CA nội bộ vào kho chứng chỉ Windows (thường là Nhà cung cấp chứng chỉ gốc tin cậy của máy tính cục bộ). Tắt xác thực trong mã nghĩa là không phát hiện được tấn công người đứng giữa khi ứng dụng dùng trên mạng ngoài, và lỗ hổng vẫn còn.