ソケットアクティベーションを使用したsystemdユーザーユニットを介したオンデマンドSSH Socksプロキシが、希望どおりに再起動しない


14

隔離されたネットワークに到達するには、 -D を使用し

に追加するたびに詳細を入力する必要を避けるために~/.ssh/config

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

次に、サービスユニット定義ファイルを作成しました。

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

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

[Install]
WantedBy=default.target

デーモンに新しいサービス定義をリロードさせ、新しいサービスを有効にし、開始し、ステータスを確認し、リスニングしていることを確認させました。

$ 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

これは意図したとおりに機能します。それから、オンデマンド(再)スポーンのためにを使用することにより、サービスを手動で開始したり、で永続的に実行したりする必要を避けたいと。それはうまくいきませんでした、(私のバージョンの)ソケットファイル記述子を受け取ることができないと思います。 ssh

私は、ドキュメント(見つかった12)、および例えば、使用するためのsystemd-socket-proxyd2「ラッパー」サービス、「サービス」と「ソケット」を作成する-toolを:

$ 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

これうまくいくようですssh死ぬか殺されるです。そうすると、次回の接続試行時に再生成されなくなります。

質問:

  1. / usr / bin / sshはsystemdで渡されたソケットを実際に受け入れられませんか?それとも新しいバージョンだけですか?私のものはup2date Debian 8.9のものです。
  2. ルートのユニットのみがこのBindTodeviceオプションを使用できますか?
  3. 古いトンネルが停止した後、最初の新しい接続でプロキシサービスが正しく再生成されないのはなぜですか?
  4. これは「オンデマンドssh socksプロキシ」を設定する正しい方法ですか?そうでない場合、どのようにそれを行いますか?

autossh接続が失敗した場合に再接続を処理する必要があります(ただし、システムの方法ではありません)。
-Jakuje

@Jakuje:コメントはありますが、接続が永続的であることは望みません。私はそれを使用するときにそれを生成し、(理想的には、x分でデータが送信されないタイムアウトの後に)自己終了させます。また、以前のソリューションではを使用しましたautossh
アレックスストラギーズ

回答:


4
  • / usr / bin / sshはsystemdで渡されたソケットを実際に受け入れられませんか?

私はそれを考慮して、それほど驚くことではないと思います:

  • OpenSSHはOpenBSDプロジェクトです
  • systemdはLinuxカーネルのみをサポートします
  • systemdのサポートは、オプション/ビルド時の依存関係としてOpenSSHに明示的に追加する必要があります。

  • ルートのユニットのみがこのBindTodeviceオプションを使用できますか?

ユーザーsystemdインスタンスは一般的にかなり隔離されており、たとえばメインpid-0インスタンスと通信できません。ユーザーユニットファイルからシステムユニットに依存するようなことはできません。

BindToDevice言及のドキュメント:

このパラメーターを設定すると、ユニットに追加の依存関係が追加される可能性があることに注意してください(上記を参照)。

上記の制限のため、オプションはユーザーsystemdインスタンスからは機能しないことを意味します。


  • 古いトンネルが停止した後、最初の新しい接続でプロキシサービスが正しく再生成されないのはなぜですか?

私が理解しているように、一連のイベントは次のとおりです。

  • SocksProxyHelper.socket 開始されます。
  • SOCKSクライアントはlocalhost:8118に接続します。
  • systemdが起動しSocksProxyHelper.serviceます。
  • の依存関係としてSocksProxyHelper.service、systemdも起動しSocksProxy.serviceます。
  • systemd-socket-proxydsystemdソケットを受け入れ、そのデータをに転送します ssh
  • ssh 死ぬか殺されます。
  • systemdは通知SocksProxy.serviceし、非アクティブ状態にしますが、何もしません。
  • SocksProxyHelper.serviceは実行を続けて接続を受け入れますが、実行さsshれていないため、への接続に失敗します。

修正はに追加するBindsTo=SocksProxy.serviceことSocksProxyHelper.serviceです。ドキュメントの引用(強調を追加):

要件の依存関係を構成しますRequires=。スタイルはに非常に似ています。ただし、この依存タイプはより強力です。バインドされたユニットが停止すると、このユニットも停止するRequires=ことを宣言します。これは、突然非アクティブ状態になった別のユニットにバインドされたユニットも停止されることを意味します。ユニットは、さまざまな理由で突然、予期せずに非アクティブ状態になります。サービスユニットのメインプロセスは、独自の選択で終了する場合がありますでたり、デバイスユニットのバッキングデバイスが取り外されたり、システムおよびサービスマネージャー。

After=同じユニットでと組み合わせて使用​​すると、の動作BindsTo=がさらに強くなります。この場合、このユニットもアクティブ状態になるには、にバインドされたユニットが厳密にアクティブ状態である必要があります。(のようなこれが突然非アクティブ状態に入ることを別のユニットに結合された単位を意味するだけでなく、失敗による状態チェックをスキップ取得する別のユニットに結合されるものではないだけでConditionPathExists=ConditionPathIsSymbolicLink=それをすべきで、停止されます-下記参照します、...)走っている。したがって、多くの場合、と組み合わせることをお勧めBindsTo=After=ます。


  • これは「オンデマンドssh socksプロキシ」を設定する正しい方法ですか?そうでない場合、どのようにそれを行いますか?

おそらく「正しい方法」はありません。この方法には長所(すべてが「オンデマンド」)と短所(systemdへの依存、sshがまだリッスンを開始していないために最初の接続が通過しない)があります。おそらく、autosshでsystemdソケットアクティベーションサポートを実装する方がより良いソリューションでしょう。


BindsTo=SocksProxy.serviceファイルのUnitセクションの行の~/.config/systemd/user/SocksProxyHelper.service後に追加しましたAfter=SocksProxy.service。SSHが停止またはgets_killedになったときに、SocksProxyサービスを手動で再起動する必要がなくなりました。systemdがTCP接続をリセットしないように、初期接続を「保持」する方法はありますか?
アレックスストラージス

@Vladimir Panteleev明確にしたい一点:systemdソケットのアクティブ化のサポートは$LISTEN_FDS、に依存関係を追加せずに解析することで比較的簡単に実装できるsd_listen_fds()ので、まだ難しい販売かもしれませんが、それほど難しくありません。
アミール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.