ICE candidate và proxy: vì sao đổi IP vẫn thấy địa chỉ máy thật
Mình tên Đức, ở quận Tân Bình, TP.HCM, chăm Zalo OA cho bốn brand mỹ phẩm. Cuối tuần trước mình cấu hình lại cửa sổ: mua SOCKS5, dán host:port vào từng profile, bấm Test Connection thấy xanh, mở trang kiểm tra IP thì đúng hiện khu vực cần. Mừng chưa được năm phút, mình lăn tăn mở thêm browserleaks.com/webrtc, ôi trời, bảng vẫn nằm im một dãy 192.168.x.x với một địa chỉ public quen quá, hóa ra là của chính nhà mình. Ngồi hình ra mấy phút, tưởng proxy hỏng. Loay hoay đổi sang nhà thứ hai rồi thứ ba, dòng 192.168 vẫn đứng yên. Đau đầu thật. Đến lúc mở phần cấu hình dấu vân tay trong BitBrowser, thấy mỗi cửa sổ có tùy chọn WebRTC khớp theo tham số proxy, mình mới khựng lại: chỗ cần chỉnh không nằm ở đường mạng mình vẫn đổ lỗi.
Rò rỉ WebRTC và người chạy Zalo OA: tưởng hỏng proxy, hóa ra lệch tầng
Nói rõ ngay: proxy vẫn chạy đúng, trang web vẫn hiện đúng IP exit, chẳng hỏng gì. Cái gọi là rò rỉ WebRTC nằm ở tầng khác hẳn. Nói đơn giản, mấy trang kiểm tra không hỏi theo đường HTTP, chúng dựng một kết nối WebRTC rồi đọc những gì trình duyệt tự thu thập. Dân vận hành Zalo OA, mỗi brand một môi trường riêng để trả lời đúng múi giờ, dễ hiểu lầm lắm: tưởng mọi thứ đã qua proxy, ai ngờ vẫn còn một đường rẽ. Soi từng lớp là thấy ngay, đổi proxy lần thứ tư chỉ tốn công.
ICE candidate, STUN và host candidate: dân kỹ thuật soi tới cái UDP socket
Mổ xẻ bên trong mới là chỗ đáng nói. Trang gọi new RTCPeerConnection kèm STUN hoặc TURN, trình duyệt khởi động ICE agent, tức Interactive Connectivity Establishment, lục card mạng rồi sinh mấy loại ICE candidate. host candidate là địa chỉ riêng của máy, kiểu 192.168.1.23, hoặc Chrome đời mới thay bằng tên mDNS như xxxx-xxxx.local để đỡ lộ số cụ thể. srflx, tức server reflexive, là ICE gửi gói tin ra STUN rồi đọc lại địa chỉ public mà NAT vừa map. Đường trực tiếp không thông thì mượn relay candidate qua TURN. Cả chuỗi đẩy về trang qua onicecandidate, event.candidate.candidate là chuỗi SDP mà JavaScript đọc trực tiếp được. Một đoạn script nhỏ là trang biết địa chỉ nội bộ, tên mDNS lẫn public IP thật, ghép thành bức tranh mạng đối chiếu IP exit.
Và đây là cú lật: WebRTC không chui qua đường hầm CONNECT của HTTP proxy. ICE tự mở một UDP socket riêng, nằm ở tầng vận chuyển do trình duyệt quản, còn proxy HTTP hay SOCKS5 mình khai chỉ lo luồng HTTP. Hai đường chạy song song, không tự gộp vào nhau. Nên đổi IP xong mà cột WebRTC vẫn còn 192.168.x.x là hiện tượng lệch tầng giao thức, chuyện thường thôi, không phải proxy hỏng hay dán nhầm host. Cả vòng lặp: trang dựng kết nối, ICE gom candidate, script đọc SDP, so với IP exit, khớp thì qua, lệch thì quay lại chỉnh cấu hình. Nắm một câu này là đỡ đổi nhà cung cấp vô ích.
Cấu hình WebRTC trong nhân cho studio nhiều thiết bị: DNS với IPv6 đứng riêng
Hiểu rồi thì xử lý nhẹ tênh, thuần túy đưa cấu hình về đúng chỗ. Ở tầng nhân, tùy chọn WebRTC của mỗi hồ sơ cho chọn vài hướng: ngừng thu thập candidate, thay tham số bằng địa chỉ khớp proxy, hoặc tự khớp theo IP vừa gán. BitBrowser làm bằng một lớp hook C++ trong engine, nên JavaScript gọi WebRTC thì đọc về tham số đã cấu hình cho profile đó, không phải thông số máy thật. Mỗi hồ sơ cất riêng thiết lập trong phân vùng lưu trữ, Cookie, localStorage, tham số mạng đều tách bạch. Với studio ứng dụng chạy nhiều thiết bị song song, lúc cần danh tính thiết bị riêng kèm nhà mạng và SIM khớp theo IP thì BitCloudPhone đáp ứng phần đó.
Đừng gật xong một mình WebRTC. Còn hai bề mặt lộ thông tin khác, không dính tới ICE. DNS: truy vấn phân giải đi thẳng tới resolver nhà mạng thay vì theo proxy là trang đích vẫn đoán được mình ngồi đâu, dù IP exit đã đúng. IPv6: nhiều proxy chỉ xử lý IPv4, máy có IPv6 native là luồng này đi ra bằng địa chỉ thật. Ba cái xếp cạnh nhau, rà soát phải soi đủ ba.

Tự kiểm tra bằng JavaScript cho developer: quy trình 5 bước
Với dân developer, mình hay dùng Local API của BitBrowser quét cả chục cửa sổ, gắn sẵn một bước kiểm tra trước khi chạy script. Đoạn dưới chỉ để kiểm tra cấu hình của chính mình, in mấy dòng host với srflx so với IP exit.
// chỉ để kiểm tra cấu hình của chính mình
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
pc.createDataChannel('kiem-tra');
pc.onicecandidate = function (event) {
if (!event.candidate) return;
const dong = event.candidate.candidate;
if (dong.indexOf('typ host') !== -1 || dong.indexOf('typ srflx') !== -1) {
console.log(dong);
}
};
pc.createOffer().then(function (offer) { return pc.setLocalDescription(offer); });
Quy trình mình vẫn làm, gọn trong năm bước:
- Mở cửa sổ, ghi lại IP exit và khu vực proxy gán.
- Chạy script, chép lại dòng host với srflx in ra.
- Mở browserleaks.com/webrtc và whoer.net, so địa chỉ công khai với IP exit.
- Đối chiếu DNS với IPv6 trên ipleak.net, xem dòng nào lệch.
- Khớp thì lưu kết quả, lệch thì quay về tùy chọn WebRTC của hồ sơ.
Vài vòng là quen. Dù quét cả chục profile, mình vẫn bám điều khoản dịch vụ của trang đích, việc thu thập và phân tích dữ liệu chỉ trong phạm vi cho phép, có sự đồng ý khi đụng dữ liệu cá nhân theo Nghị định 13/2023/NĐ-CP. Công cụ lo môi trường, tuân thủ là của mình.
biến việc rà soát WebRTC thành thói quen của cả đội
Nhìn lại chiều loay hoay vì rò rỉ WebRTC hôm đó, điều mình mang theo là sửa được cách nhìn. Mình tưởng đổi proxy là xong, ai ngờ thứ cần chỉnh nằm ở tầng UDP, rồi mới kéo DNS với IPv6 vào cùng bảng soi. Đoán cảm giác lại tốn công đổi nhà cung cấp, trong khi soi năm bước ra ngay chỗ lệch. Mình nghĩ phía nền tảng sẽ soi kỹ hơn ở tầng vận chuyển lẫn thiết bị, tín hiệu không chỉ còn IP hay Cookie mà lan xuống cách client mở socket hay phân giải tên miền. Nên thay vì đợi có cảnh báo mới hốt hoảng, cứ đưa checklist vào quy trình trước mỗi đợt lên sóng, ghi kết quả từng cửa sổ. BitBrowser hay công cụ khác cũng chỉ gọn phần cấu hình; vận hành ổn định vẫn nằm ở tuân theo quy chuẩn vận hành và chấp hành điều khoản dịch vụ. Nhẹ đầu hơn cái cảnh sáng ra lại dán host:port.
All rights reserved