SSH theo yêu cầu proxy qua các đơn vị người dùng systemd với kích hoạt ổ cắm không khởi động lại như mong muốn


14

Để truy cập một mạng bị cô lập, tôi sử dụng -D .

Để tránh phải nhập các chi tiết mỗi lần tôi thêm chúng vào ~/.ssh/config:

$ awk '/Host socks-proxy/' RS= ~/.ssh/config
Host socks-proxy
  Hostname pcit
  BatchMode yes
  RequestTTY no
  Compression yes
  DynamicForward localhost:9118

Sau đó, tôi đã tạo một tệp định nghĩa đơn vị dịch vụ :

$ cat ~/.config/systemd/user/SocksProxy.service 
[Unit]
Description=SocksProxy Over Bridge Host

[Service]
ExecStart=/usr/bin/ssh -Nk socks-proxy

[Install]
WantedBy=default.target

Tôi để trình nền tải lại các định nghĩa dịch vụ mới, kích hoạt dịch vụ mới, khởi động nó, kiểm tra trạng thái của nó và xác minh rằng nó đang lắng nghe:

$ systemctl --user daemon-reload
$ systemctl --user list-unit-files | grep SocksP
SocksProxy.service   disabled

$ systemctl --user enable SocksProxy.service
Created symlink from ~/.config/systemd/user/default.target.wants/SocksProxy.service to ~/.config/systemd/user/SocksProxy.service.

$ systemctl --user start SocksProxy.service 
$ systemctl --user status SocksProxy.service 
● SocksProxy.service - SocksProxy Over Bridge Host
   Loaded: loaded (/home/alex/.config/systemd/user/SocksProxy.service; enabled)
   Active: active (running) since Thu 2017-08-03 10:45:29 CEST; 2s ago
 Main PID: 26490 (ssh)
   CGroup: /user.slice/user-1000.slice/user@1000.service/SocksProxy.service
           └─26490 /usr/bin/ssh -Nk socks-proxy

$ netstat -tnlp | grep 118
tcp     0    0 127.0.0.1:9118        0.0.0.0:*             LISTEN     
tcp6    0    0 ::1:9118              :::*                  LISTEN

Điều này hoạt động như dự định. Sau đó, tôi muốn tránh phải tự khởi động dịch vụ hoặc chạy vĩnh viễn với , bằng cách sử dụng để sinh sản theo yêu cầu (tái). Điều đó không hiệu quả, tôi nghĩ (phiên bản của tôi) không thể nhận được mô tả tệp ổ cắm.ssh

Tôi đã tìm thấy tài liệu ( 1 , 2 ) và một ví dụ cho việc sử dụng systemd-socket-proxyd-tool để tạo 2 dịch vụ "trình bao bọc", "dịch vụ" và "ổ cắm":

$ cat ~/.config/systemd/user/SocksProxyHelper.socket 
[Unit]
Description=On Demand Socks proxy into Work

[Socket]
ListenStream=8118
#BindToDevice=lo
#Accept=yes

[Install]
WantedBy=sockets.target

$ cat ~/.config/systemd/user/SocksProxyHelper.service 
[Unit]
Description=On demand Work Socks tunnel
After=network.target SocksProxyHelper.socket
Requires=SocksProxyHelper.socket SocksProxy.service
After=SocksProxy.service

[Service]
#Type=simple
#Accept=false
ExecStart=/lib/systemd/systemd-socket-proxyd 127.0.0.1:9118
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

$ systemctl --user daemon-reload

Điều này dường như làm việc, cho đến khi sshchết hoặc bị giết. Sau đó, nó sẽ không tái sinh ở lần thử kết nối tiếp theo khi cần.

Câu hỏi:

  1. Có thể / usr / bin / ssh thực sự không chấp nhận ổ cắm được truyền qua systemd không? Hay chỉ có phiên bản mới hơn? Của tôi là một trong số up2date Debian 8.9 .
  2. Chỉ có thể đơn vị root sử dụng BindTodevicetùy chọn?
  3. Tại sao dịch vụ proxy của tôi không hồi đáp chính xác trên kết nối mới đầu tiên sau khi đường hầm cũ bị chết?
  4. Đây có phải là cách phù hợp để thiết lập "proxy ssh vớ theo yêu cầu" không? Nếu, không, làm thế nào để bạn làm điều đó?

autosshnên quan tâm đến việc kết nối lại trong trường hợp kết nối không thành công (mặc dù đó không phải là cách hệ thống).
Jakuje

@Jakuje: Thx cho nhận xét, nhưng tôi không muốn kết nối là vĩnh viễn. Tôi muốn nó được sinh ra khi tôi sử dụng nó, và sau đó (lý tưởng nhất là sau khi hết thời gian chờ dữ liệu được gửi trong thời gian x-phút). Ngoài ra, giải pháp trước đây của tôi được sử dụng autossh.
Alex Stragies

Câu trả lời:


4
  • Có thể / usr / bin / ssh thực sự không chấp nhận ổ cắm được truyền qua systemd không?

Tôi nghĩ rằng điều đó không quá ngạc nhiên, xem xét:

  • OpenSSH là một dự án OpenBSD
  • systemd chỉ hỗ trợ kernel Linux
  • Hỗ trợ systemd sẽ cần phải được thêm một cách rõ ràng vào OpenSSH, như là một phụ thuộc tùy chọn / thời gian xây dựng, vì vậy nó có thể sẽ là một khó bán.

  • Chỉ có thể đơn vị root sử dụng BindTodevicetùy chọn?

Các cá thể systemd của người dùng thường khá tách biệt và ví dụ: không thể giao tiếp với cá thể pid-0 chính. Những thứ như tùy thuộc vào đơn vị hệ thống từ tệp đơn vị người dùng là không thể.

Các tài liệu cho BindToDeviceđề cập:

Lưu ý rằng việc đặt tham số này có thể dẫn đến các phụ thuộc bổ sung được thêm vào đơn vị (xem bên trên).

Do các hạn chế nêu trên, chúng tôi có thể ngụ ý rằng tùy chọn không hoạt động từ các phiên bản systemd của người dùng.


  • Tại sao dịch vụ proxy của tôi không hồi đáp chính xác trên kết nối mới đầu tiên sau khi đường hầm cũ bị chết?

Theo tôi hiểu, chuỗi sự kiện như sau:

  • SocksProxyHelper.socket được bắt đầu.
  • Một máy khách SOCKS kết nối với localhost: 8118.
  • systemd bắt đầu SocksProxyHelper.service.
  • Là một phụ thuộc của SocksProxyHelper.service, systemd cũng bắt đầu SocksProxy.service.
  • systemd-socket-proxydchấp nhận ổ cắm systemd và chuyển tiếp dữ liệu của nó tới ssh.
  • ssh chết hoặc bị giết
  • thông báo systemd, và đặt SocksProxy.servicevào trạng thái không hoạt động, nhưng không làm gì cả.
  • SocksProxyHelper.servicetiếp tục chạy và chấp nhận các kết nối, nhưng không kết nối được ssh, vì nó không còn chạy nữa.

Cách khắc phục là thêm BindsTo=SocksProxy.servicevào SocksProxyHelper.service. Trích dẫn tài liệu của nó (nhấn mạnh thêm):

Định cấu hình phụ thuộc yêu cầu, rất giống trong phong cách Requires=. Tuy nhiên, loại phụ thuộc này mạnh hơn: ngoài tác dụng của Requires=nó tuyên bố rằng nếu đơn vị bị ràng buộc bị dừng, đơn vị này cũng sẽ bị dừng . Điều này có nghĩa là một đơn vị bị ràng buộc với một đơn vị khác đột nhiên rơi vào trạng thái không hoạt động cũng sẽ bị dừng. Các đơn vị có thể đột ngột, đột ngột vào trạng thái không hoạt động vì các lý do khác nhau: quy trình chính của đơn vị dịch vụ có thể tự chấm dứt , thiết bị sao lưu của đơn vị thiết bị có thể được rút ra hoặc điểm gắn của đơn vị gắn kết có thể bị ngắt mà không có sự tham gia của người quản lý hệ thống và dịch vụ.

Khi được sử dụng cùng với After=trên cùng một đơn vị, hành vi của BindsTo=thậm chí còn mạnh hơn. Trong trường hợp này, đơn vị bị ràng buộc phải ở trạng thái hoạt động để đơn vị này cũng ở trạng thái hoạt động . Điều này không chỉ có nghĩa là một đơn vị bị ràng buộc với một đơn vị khác đột nhiên rơi vào trạng thái không hoạt động, mà còn một đơn vị bị ràng buộc với một đơn vị khác bị bỏ qua do kiểm tra điều kiện không thành công (chẳng hạn như ConditionPathExists=, ConditionPathIsSymbolicLink=- - xem bên dưới) sẽ bị dừng đang chạy Do đó, trong nhiều trường hợp, tốt nhất là kết hợp BindsTo=với After=.


  • Đây có phải là cách phù hợp để thiết lập "proxy ssh vớ theo yêu cầu" không? Nếu, không, làm thế nào để bạn làm điều đó?

Có lẽ không có "cách đúng". Phương pháp này có ưu điểm của nó (mọi thứ là "theo yêu cầu") và nhược điểm (phụ thuộc vào systemd, kết nối đầu tiên không được thông qua vì ssh chưa bắt đầu nghe). Có lẽ thực hiện hỗ trợ kích hoạt ổ cắm systemd trong autossh sẽ là một giải pháp tốt hơn.


Tôi đã thêm vào BindsTo=SocksProxy.servicephần Đơn vị của tệp ~/.config/systemd/user/SocksProxyHelper.service, sau After=SocksProxy.servicedòng. Việc khởi động lại thủ công Dịch vụ của VớProxy bây giờ không còn cần thiết nữa, khi SSH chết / got_kills. Có cách nào để systemd "giữ" kết nối ban đầu, để nó không được thiết lập lại TCP không?
Alex Stragies

@Vladimir Panteleev một điểm tôi muốn làm rõ: hỗ trợ kích hoạt socket systemd có thể được thực hiện tương đối dễ dàng bằng cách phân tích cú pháp $LISTEN_FDSmà không cần thêm phụ thuộc vào sd_listen_fds(), vì vậy nó vẫn có thể khó bán, nhưng không quá khó.
Amir
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.