VPN không chặn psql: ứng dụng khách của bạn đi nơi khác
psql và một ứng dụng khách GUI có thể nhắm tới những điểm cuối khác nhau từ cùng một máy. Hãy so sánh máy chủ, socket, vai trò và TLS trước khi đổ lỗi cho VPN.
Cả hai ứng dụng khách đều nằm trên cùng một máy tính xách tay, đi qua cùng một đường hầm, và chỉ một trong hai kết nối được. Sự so sánh đó có vẻ là bằng chứng rằng VPN đang chọn lọc, trong khi lời giải thích phổ biến hơn nhiều là hai ứng dụng khách nhắm tới những đích khác nhau. Một GUI giữ máy chủ, cổng, vai trò và cài đặt TLS của riêng nó rồi lặng lẽ dựng một chuyển tiếp SSH khi cần, còn psql lắp ghép kết nối từ các giá trị mặc định của libpq mà shell của bạn có thể đã đặt sẵn. Tái tạo kết nối đang hoạt động là việc đọc cài đặt của GUI, không phải cài lại đường hầm.
Huyền thoại: một ứng dụng khách hoạt động chứng minh đường đi
Nếu GUI kết nối được, đường hầm có chuyển lưu lượng, và đó là tất cả những gì GUI chứng minh. Nó không nói gì về địa chỉ mà psql phân giải, vai trò mà nó xác thực hay việc socket nó mở có bao giờ rời khỏi máy hay không. Đường đi được chia sẻ; các tham số thì không.
Một chuyển tiếp cục bộ làm khoảng cách rộng hơn. GUI có thể kết nối tới 127.0.0.1 trên cổng mà nó đã chuyển tiếp qua SSH, và bộ lắng nghe đó chỉ tồn tại trong suốt phiên GUI. psql trỏ tới localhost mà không có chuyển tiếp sẽ nhận một kết nối bị từ chối, chẳng liên quan gì đến VPN.
Đọc điểm cuối mà GUI thực sự dùng
Mở thuộc tính của kết nối và sao chép bốn giá trị: máy chủ, cổng, cơ sở dữ liệu và vai trò. Sau đó tìm một tab đường hầm, vì chuyển tiếp SSH biến một địa chỉ riêng thành cổng cục bộ và thay đổi điều phải nói với psql.
| Setting | What the GUI holds | What psql uses when the value is absent |
|---|---|---|
| Destination | A saved hostname, sometimes behind a forward | A local Unix socket, not the remote endpoint |
| Port | The direct port or a forwarded local port | 5432, or the port from a service file |
| Role and database | Stored per connection profile | Your operating-system user name |
| TLS identity | Its own CA bundle and verification mode | Whatever PGSSLMODE or the service file says |
| Startup files | Not read at all | Read unless -X is passed |
Mỗi hàng hỏng ở một tầng khác nhau, và thông báo bạn nhận được gọi tên tầng đó. Dán tên thân thiện của hồ sơ đã lưu vào psql không mang theo giá trị nào ở trên, và tên dịch vụ được phân giải qua một tệp mà terminal có lẽ không bao giờ đọc.
libpq thừa hưởng gì từ shell của bạn
psql là một ứng dụng khách mỏng trên libpq, và libpq đọc môi trường trước khi đọc bất cứ thứ gì khác. Các biến như PGHOST, PGHOSTADDR, PGPORT, PGDATABASE, PGUSER, PGSERVICE và PGSSLMODE mỗi biến đều có thể chuyển hướng một phần kết nối. Chúng được thừa hưởng chứ không được gõ vào, nên không gì trong lệnh bạn chạy hiển thị chúng. Một PGSSLMODE được xuất cũng có thể thay đổi điều ứng dụng khách chấp nhận mà không cần một từ nào trên dòng lệnh.
Hai trong số các biến đó đáng bị nghi ngờ trước tiên. PGHOSTADDR cung cấp một đích số vượt qua phân giải tên trong khi tên máy chủ vẫn quyết định danh tính chứng chỉ, và PGSERVICE kéo máy chủ, cơ sở dữ liệu và lựa chọn TLS ra khỏi một tệp dịch vụ. Đổ toàn bộ môi trường để gỡ lỗi là thói quen xấu, vì nó có thể chứa mật khẩu và token không liên quan; thay vào đó hãy chọn những biến bạn quan tâm.
Bỏ qua cả host và hostaddr sẽ chọn socket miền Unix thay vì địa chỉ mạng. Vì vậy một lệnh gọi psql không có -h có thể thành công cục bộ, hoặc thất bại với lỗi socket, mà không bao giờ chạm tới tuyến đường mà GUI dùng.
Gửi đúng các tham số đó bằng tay
Với các giá trị của GUI trong tay, hãy truyền chúng một cách tường minh và bỏ qua tệp khởi động có thể thêm phần ghi đè. Chuỗi kết nối bên dưới chỉ là ví dụ: thay điểm cuối, cổng, cơ sở dữ liệu và vai trò bằng các giá trị mà quản trị viên của bạn đã phê duyệt, và giữ nguyên cấu hình tin cậy vốn đã hoạt động.
psql -X "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5"Ba chi tiết trong lệnh đó là có chủ ý. -X chặn tệp khởi động của psql, dù không chặn môi trường của libpq hay một định nghĩa dịch vụ. connect_timeout=5 ngăn một tuyến đường bế tắc treo terminal trong nhiều phút. sslmode=verify-full giữ bật kiểm tra chứng chỉ và tên máy chủ, đúng là phần mà người ta tắt đi khi lỗi TLS xuất hiện.
Nếu điểm cuối đã được phê duyệt nằm sau một pooler, cổng 6432 và cổng 5432 có thể tới cùng dữ liệu qua các danh tính máy chủ khác nhau, và việc xác minh có thể thất bại ở tên của pooler thay vì tên cơ sở dữ liệu. Hãy sửa tên trong chuỗi kết nối thay vì làm yếu chế độ.
Để thông báo lỗi chọn bước tiếp theo
Văn bản thất bại cho biết nỗ lực đã đi được bao xa, và điều đó tốt hơn mọi phỏng đoán về đường hầm. Một tên không phân giải được sẽ hỏng trước khi có socket, hết thời gian nghĩa là tuyến đường hoặc tường lửa đã bỏ gói tin, bị từ chối nghĩa là có thứ gì đó đã trả lời và từ chối, và lỗi xác thực nghĩa là mạng đã hoạt động rồi.
psql -X -w "host=db.internal.example port=6432 dbname=orders user=report_ro sslmode=verify-full connect_timeout=5" -c '\conninfo'
env | grep -E '^PG'
psql --versionSo sánh đầu ra của \conninfo với phiên trực tiếp của GUI: cùng máy chủ, cùng cổng, cùng vai trò, cùng trạng thái TLS. Khi bốn điều đó khớp nhau, VPN không còn gì để giải thích. Cho tới khi chúng khớp, mọi thay đổi thêm vào đường hầm đều là phỏng đoán về một kết nối mà terminal chưa bao giờ tạo ra.