Ngay cả một laptop sau NAT của nhà mạng cũng có thể phục vụ đồng nghiệp, miễn là máy chủ VPN đóng vai trò điểm hẹn. Hai cơ chế dẫn tới đó: máy khách gọi ra ngoài và đề nghị máy chủ giữ một cổng lắng nghe, hoặc máy chủ công bố một cổng và dịch nó vào đường hầm. Cả hai đều giải quyết cùng một vấn đề tiếp cận và hành xử khác nhau khi có sự cố, giám sát và ghi nhật ký. Ba điều kiện quyết định cái nào phù hợp với thiết lập của bạn.

Hai hình thức, một điểm hẹn

Ở hình thức thứ nhất, máy khách mở một phiên SSH ra ngoài và đề nghị máy chủ lắng nghe trên một cổng đã chọn, gửi mọi kết nối trở lại qua phiên đó. Trên máy chủ không có gì được chuyển tiếp và không có chuyển đổi gói tin nào diễn ra, vì vậy yêu cầu duy nhất là một tài khoản SSH, một chuyển tiếp được phép và một quy tắc tường lửa cho cổng đó. Dịch vụ vẫn gắn với loopback trên máy khách, điều thường là cái bạn muốn.

ssh -N -R 8081:127.0.0.1:8080 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 [email protected]

Ở hình thức thứ hai, máy chủ sở hữu cổng công khai và viết lại mọi kết nối về phía địa chỉ đường hầm của máy khách. Việc này cần bật chuyển tiếp IP, dịch địa chỉ đích ở đầu vào và dịch địa chỉ nguồn ở đầu ra, và nó vẫn hoạt động khi không có phiên SSH nào. Cổng thuộc về máy chủ chứ không thuộc về một phiên, và chính thuộc tính đó quyết định phần lớn các trường hợp thực tế.

Không hình thức nào an toàn hơn về bản chất. Cả hai cuối cùng đều phơi bày một cổng dịch vụ cho bất kỳ ai tiếp cận được địa chỉ công khai của máy chủ, và cả hai vẫn phụ thuộc vào xác thực của chính dịch vụ.

Điều kiện một: cổng có phải sống lâu hơn phiên không

Một chuyển tiếp ngược chỉ sống đúng bằng phiên SSH đã tạo ra nó. Khi liên kết đứt, bộ lắng nghe biến mất và đồng nghiệp thấy kết nối bị từ chối thay vì một đường chậm. Việc giám sát lệnh bằng một unit systemd và chính sách khởi động lại khắc phục điều đó, và ExitOnForwardFailure=yes làm cho việc gắn kết thất bại hiện ra ngay thay vì để lại một phiên chạy mà không có chuyển tiếp.

Một cổng đã dịch vẫn sống sót qua khởi động lại nếu các quy tắc được lưu bền, nhưng nó phụ thuộc vào việc máy khách giữ nguyên địa chỉ đường hầm. Một nhóm động cấp cho laptop địa chỉ khác sau khi kết nối lại sẽ âm thầm trỏ quy tắc vào hư không. Hãy đặt trước địa chỉ đường hầm, sau đó viết quy tắc, và coi hai việc là một thay đổi.

Nếu dịch vụ phải trả lời lúc ba giờ sáng mà không ai nhìn, hình thức có cổng do máy chủ công bố có ít bộ phận chuyển động hơn, vì tiến trình duy nhất phải duy trì là chính đường hầm.

Điều kiện hai: tường lửa và nhật ký thuộc về ai

Hình thức ngược giữ toàn bộ chính sách ở hai nơi. sshd quyết định qua AllowTcpForwarding liệu chuyển tiếp từ xa có được phép hay không, và GatewayPorts quyết định bộ lắng nghe gắn với loopback hay với mọi địa chỉ. Với giá trị mặc định no, đồng nghiệp bên ngoài máy chủ không tiếp cận được cổng dù chuyển tiếp đã thành công, và điều đó trông như đường hầm hỏng trong khi thực ra là địa chỉ gắn kết.

sudo ss -ltn '( sport = :8081 )'
sudo grep -E '^(GatewayPorts|AllowTcpForwarding)' /etc/ssh/sshd_config

Hình thức đã dịch cần bật chuyển tiếp và hai quy tắc, và quy tắc thứ hai là nơi hầu hết công thức sai. Giới hạn việc dịch địa chỉ nguồn theo trạng thái conntrack DNAT nghĩa là chỉ những kết nối do quy tắc đích tạo ra mới được viết lại, chứ không phải mọi gói tin máy chủ gửi vào đường hầm.

sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8081 -j DNAT --to-destination 10.88.0.6:8080
sudo iptables -t nat -A POSTROUTING -o tun0 -m conntrack --ctstate DNAT -j SNAT --to-source 10.88.0.1

Việc viết lại đó cũng phá hủy khả năng quy trách nhiệm. Sau đó máy khách thấy mọi người gọi đều là địa chỉ đường hầm của máy chủ, điều này gộp mọi giới hạn tốc độ theo địa chỉ vào một xô và che mất ai đã gửi gì. Nếu việc quy trách nhiệm quan trọng, hãy kết thúc kết nối trên máy chủ hoặc giữ quyết định cho phép ở đó và truyền danh tính trong một tiêu đề mà dịch vụ tin cậy. Việc chọn giữa hai cách sửa đó phụ thuộc vào việc dịch vụ có đọc tiêu đề proxy hay không.

Điều kiện ba: một cổng hay nhiều cổng, và tên thuộc về ai

Một dịch vụ trên một cổng là trường hợp chuyển tiếp ngược thắng về công sức. Bạn cần một lệnh, một tài khoản và một quy tắc tường lửa, và việc dọn dẹp là giết phiên. Nhiều dịch vụ trên cùng một địa chỉ công khai đẩy bạn về hình thức do máy chủ công bố, vì mỗi chuyển tiếp ngược cần cổng máy chủ riêng và tập hợp lớn dần theo từng dịch vụ.

Tên miền làm mọi thứ phức tạp hơn. Một chuyển tiếp ngược có thể nằm sau proxy TCP định tuyến theo SNI, trong khi cổng đã dịch thường là một cổng cho mỗi dịch vụ. Nếu dịch vụ tự kết thúc TLS và cần tên máy chủ gốc, cách proxy giữ được nó và cách DNAT chỉ giữ được nếu dịch vụ chấp nhận tên đó trên cổng đó.

Hãy ghi lại điều kiện nào trong ba điều kiện đã quyết định hình thức. Nếu không, người tiếp theo thêm dịch vụ thứ hai sẽ mở lại cùng phép so sánh với ít ngữ cảnh hơn.

Hãy quyết định, rồi kiểm tra từ bên ngoài

Kiểm tra đường đi từ một mạng không có tuyến nào tới laptop, và quan sát các bộ đếm trên máy chủ trong khi yêu cầu chạy. Kiểm tra từ máy chủ tới địa chỉ công khai của chính nó không chứng minh được gì ở đây, vì gói tin được tạo cục bộ và không bao giờ tới móc dịch địa chỉ đầu vào, nên bài kiểm tra có thể đạt trong khi đường thật đã hỏng.

sudo iptables -t nat -L PREROUTING -n -v
sudo tcpdump -ni any 'tcp port 8081' -c 20

Các bộ đếm đứng yên nghĩa là gói tin chưa bao giờ tới quy tắc, điều này chỉ ra nhà cung cấp hoặc tường lửa của máy chủ. Các bộ đếm chuyển động trong khi dịch vụ từ chối chỉ ra tường lửa của chính máy khách hoặc địa chỉ mà dịch vụ lắng nghe. Một đường hầm mang gói tin nhưng không trả lại gì là vấn đề tuyến hoặc đường ngược, và không kết quả nào trong ba kết quả này nên được gỡ lỗi bằng cách sửa bộ điều hợp của máy khách. Hãy ghi lại bộ đếm nào đã nhúc nhích trước khi bạn thay đổi bất cứ điều gì, vì bài kiểm tra tiếp theo cần đường cơ sở đó.

Khi hình thức hoạt động, hãy ghi lại cổng, chủ sở hữu và phương pháp giám sát bên cạnh cấu hình đường hầm. Một bản sửa khả năng tiếp cận chỉ tồn tại trong lịch sử shell của ai đó cách một lần khởi động lại khỏi một sự cố lặp lại.

Bài viết liên quan