[GH-ISSUE #1518] ControlSocket failed behaviour with ssh #1014

Closed
opened 2026-05-05 07:18:27 -06:00 by gitea-mirror · 9 comments
Owner

Originally created by @xundeenergie on GitHub (Sep 2, 2017).
Original GitHub issue: https://github.com/netblue30/firejail/issues/1518

Hi there!

I want to git push my repo to github.com, and i have ssh in firejail with standard-profile.
git hangs in case of hanging ssh.

ssh has a ControlMaster for multiplexed ssh-connections. And i have more than one github-repo which i update in a script one after another. So a Control-Socket is a good way, to reuse the connection.

With firejail, the first connection starts the ControlSocket, and the ssh-session for the ControlSocket (the Master) stays in foreground, so the first ssh-process stays in foreground and github cannot come to an end, because it waits for a finnished ssh-process.

If i start in another terminal another git push, it will finnish as expected.
I also can start a "ssh git@github.com" in a second terminal first, then my script with severals git push-comands will finnish.

My ~/.ssh/config contains:

Host *
ControlMaster auto
ControlPath /tmp/ssh-%r@%h:%p

But i don't know, if there is an option to send the master-connection to background.
Without firejail, the multiplexed connections will run without problems, the master connection goes to background.

Originally created by @xundeenergie on GitHub (Sep 2, 2017). Original GitHub issue: https://github.com/netblue30/firejail/issues/1518 Hi there! I want to git push my repo to github.com, and i have ssh in firejail with standard-profile. git hangs in case of hanging ssh. ssh has a ControlMaster for multiplexed ssh-connections. And i have more than one github-repo which i update in a script one after another. So a Control-Socket is a good way, to reuse the connection. With firejail, the first connection starts the ControlSocket, and the ssh-session for the ControlSocket (the Master) stays in foreground, so the first ssh-process stays in foreground and github cannot come to an end, because it waits for a finnished ssh-process. If i start in another terminal another git push, it will finnish as expected. I also can start a "ssh git@github.com" in a second terminal first, then my script with severals git push-comands will finnish. My ~/.ssh/config contains: ``` Host * ControlMaster auto ControlPath /tmp/ssh-%r@%h:%p ``` But i don't know, if there is an option to send the master-connection to background. Without firejail, the multiplexed connections will run without problems, the master connection goes to background.
gitea-mirror 2026-05-05 07:18:27 -06:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@chiraag-nataraj commented on GitHub (Aug 23, 2018):

@xundeenergie Is this still an issue?

<!-- gh-comment-id:415418708 --> @chiraag-nataraj commented on GitHub (Aug 23, 2018): @xundeenergie Is this still an issue?
Author
Owner

@SkewedZeppelin commented on GitHub (Aug 23, 2018):

@chiraag-nataraj I think I encountered this a while ago, but ended up disabling the feature for other reasons.

<!-- gh-comment-id:415431493 --> @SkewedZeppelin commented on GitHub (Aug 23, 2018): @chiraag-nataraj I think I encountered this a while ago, but ended up disabling the feature for other reasons.
Author
Owner

@chiraag-nataraj commented on GitHub (Aug 23, 2018):

Hmm okay. Lemme try this in my VM and report back.

<!-- gh-comment-id:415433044 --> @chiraag-nataraj commented on GitHub (Aug 23, 2018): Hmm okay. Lemme try this in my VM and report back.
Author
Owner

@chiraag-nataraj commented on GitHub (Aug 23, 2018):

I did a different test for various reasons:

  1. sudo ln -s /usr/local/bin/firejail /usr/local/bin/ssh
  2. sshfs user@hostname /path/to/mountpoint
  3. Verify that ssh is being run through firejail with firejail --list (it is)
  4. ssh user@hostname to test if the connection is reused
  5. Note that no authentication is requested and I'm automatically logged in

It seems like the connection is re-used, and ssh is backgrounded by the sshfs process. I don't know if this is completely equivalent to the scenario listed here though?

<!-- gh-comment-id:415444152 --> @chiraag-nataraj commented on GitHub (Aug 23, 2018): I did a different test for various reasons: 1. `sudo ln -s /usr/local/bin/firejail /usr/local/bin/ssh` 2. `sshfs user@hostname /path/to/mountpoint` 3. Verify that `ssh` is being run through firejail with `firejail --list` (it is) 4. `ssh user@hostname` to test if the connection is reused 5. Note that no authentication is requested and I'm automatically logged in It seems like the connection is re-used, and `ssh` is backgrounded by the `sshfs` process. I don't know if this is completely equivalent to the scenario listed here though?
Author
Owner

@chiraag-nataraj commented on GitHub (Aug 24, 2018):

So I followed the same process with git and had no issues. I linked /usr/local/bin/ssh -> /usr/local/bin/firejail and ran git push normally and didn't run into any issues. I'm going to close this for now, but @xundeenergie, please feel free to re-open if you still have this issue.

<!-- gh-comment-id:415624627 --> @chiraag-nataraj commented on GitHub (Aug 24, 2018): So I followed the same process with `git` and had no issues. I linked `/usr/local/bin/ssh -> /usr/local/bin/firejail` and ran `git push` normally and didn't run into any issues. I'm going to close this for now, but @xundeenergie, please feel free to re-open if you still have this issue.
Author
Owner

@mtth-bfft commented on GitHub (Sep 30, 2019):

@chiraag-nataraj Issue is 100% reproducible, and could be renamed "Firejail makes ssh with control sockets hard to use (and breaks Ansible)". For example, see the time it takes to get a prompt back, corresponding to the control process timeout:

user@localhost$ time ssh -C -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/test admin@something '/bin/sh -c "echo hello"'
Reading profile /etc/firejail/ssh.profile
Reading profile /etc/firejail/globals.local
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-passwdmgr.inc
Reading profile /etc/firejail/disable-programs.inc
Parent pid 22675, child pid 22676
Blacklist violations are logged to syslog
Child process initialized in 32.43 ms
hello

Parent is shutting down, bye...
0.04s user 0.05s system 0% cpu >>>>>>63.155<<<<<< total

From what I was able to understand, the problem is actually "by design": when SSH uses control sockets and the first connection is closed, the ssh client forks in the background to keep the TCP connection and a unix socket alive. This prevents firejail from detecting that the sandbox can be thrashed (there's still a process in it), and hangs until the control socket expires and the background process dies, which can take forever depending on SSH's config and whether the control sockets are used, prolonging the master process' life.

The problem is, you might get around the problem with individual sandboxed SSH sessions by letting them die in a terminal slowly (still, poor UX), but Ansible completely fails due to these timeouts, which forces Ansible users to disable ssh sandboxing (which is a bad thing). For example:

user@localhost$ ansible-playbook -i inventory/ servers.yml
[...]
fatal: [someserver.dot.com]: UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Reading profile /etc/firejail/ssh.profile\nReading profile /etc/firejail/globals.local\nReading profile /etc/firejail/disable-common.inc\nReading profile /etc/firejail/disable-passwdmgr.inc\nReading profile /etc/firejail/disable-programs.inc\nParent pid 21501, child pid 21502\nBlacklist violations are logged to syslog\nChild process initialized in 26.94 ms\n\nParent is shutting down, bye...",
    "unreachable": true
}

I see two possible types of "fixes" here:

  • I don't think it's really realistic, but if you think it's possible to detect that all processes in the sandbox have double-forked + created a new session to daemonize, I'd love to get started on a patch to make the sandbox itself daemonize and give back a prompt. That would keep all SSH functionalities, work with Ansible, and have a good UX if the proper messages explaining what just happened are displayed. Tell me what you think 😄
  • document the fact that Ansible is broken with the default ssh.profile, and ideally find a way to detect when SSH is started by Ansible to display that message, or disable the sandbox altogether 😢
<!-- gh-comment-id:536355478 --> @mtth-bfft commented on GitHub (Sep 30, 2019): @chiraag-nataraj Issue is 100% reproducible, and could be renamed "Firejail makes ssh with control sockets hard to use (and breaks Ansible)". For example, see the time it takes to get a prompt back, corresponding to the control process timeout: ``` user@localhost$ time ssh -C -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/test admin@something '/bin/sh -c "echo hello"' Reading profile /etc/firejail/ssh.profile Reading profile /etc/firejail/globals.local Reading profile /etc/firejail/disable-common.inc Reading profile /etc/firejail/disable-passwdmgr.inc Reading profile /etc/firejail/disable-programs.inc Parent pid 22675, child pid 22676 Blacklist violations are logged to syslog Child process initialized in 32.43 ms hello Parent is shutting down, bye... 0.04s user 0.05s system 0% cpu >>>>>>63.155<<<<<< total ``` From what I was able to understand, the problem is actually "by design": when SSH uses control sockets and the first connection is closed, the ssh client forks in the background to keep the TCP connection and a unix socket alive. This prevents firejail from detecting that the sandbox can be thrashed (there's still a process in it), and hangs until the control socket expires and the background process dies, which can take forever depending on SSH's config and whether the control sockets are used, prolonging the master process' life. The problem is, you might get around the problem with individual sandboxed SSH sessions by letting them die in a terminal slowly (still, poor UX), but Ansible completely fails due to these timeouts, which forces Ansible users to disable ssh sandboxing (which is a bad thing). For example: ``` user@localhost$ ansible-playbook -i inventory/ servers.yml [...] fatal: [someserver.dot.com]: UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Reading profile /etc/firejail/ssh.profile\nReading profile /etc/firejail/globals.local\nReading profile /etc/firejail/disable-common.inc\nReading profile /etc/firejail/disable-passwdmgr.inc\nReading profile /etc/firejail/disable-programs.inc\nParent pid 21501, child pid 21502\nBlacklist violations are logged to syslog\nChild process initialized in 26.94 ms\n\nParent is shutting down, bye...", "unreachable": true } ``` I see two possible types of "fixes" here: - I don't think it's really realistic, but if you think it's possible to detect that all processes in the sandbox have double-forked + created a new session to daemonize, I'd love to get started on a patch to make the sandbox itself daemonize and give back a prompt. That would keep all SSH functionalities, work with Ansible, and have a good UX if the proper messages explaining what just happened are displayed. Tell me what you think :smile: - document the fact that Ansible is broken with the default `ssh.profile`, and ideally find a way to detect when SSH is started by Ansible to display that message, or disable the sandbox altogether :cry:
Author
Owner

@jose1711 commented on GitHub (Jun 17, 2020):

This problem was driving me nuts thus I decided to disable firejail for Ansible's ssh completely:
ansible.cfg:

[ssh_connection]
..
ssh_executable="/usr/bin/ssh"

Another option (w/o disabling firejail) is to turn off ControlPersist option:

ssh_args = -C -o ControlMaster=auto

But for me it had some negative side-effects.

<!-- gh-comment-id:645624856 --> @jose1711 commented on GitHub (Jun 17, 2020): This problem was driving me nuts thus I decided to disable `firejail` for Ansible's `ssh` completely: `ansible.cfg`: ``` [ssh_connection] .. ssh_executable="/usr/bin/ssh" ``` Another option (w/o disabling `firejail`) is to turn off `ControlPersist` option: ``` ssh_args = -C -o ControlMaster=auto ``` But for me it had some negative side-effects.
Author
Owner

@itoffshore commented on GitHub (Oct 31, 2021):

To help people running ansible searching the web for this error:

alpine | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ",
    "unreachable": true
}

the first fix above works if you are running firejail - except do not quote the path:

[ssh_connection]
ssh_executable = /usr/bin/ssh
<!-- gh-comment-id:955721870 --> @itoffshore commented on GitHub (Oct 31, 2021): To help people running `ansible` searching the web for this error: ``` alpine | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: ", "unreachable": true } ``` [the first fix above works if you are running `firejail`](https://github.com/netblue30/firejail/issues/1518#issuecomment-645624856) - except do not quote the path: ``` [ssh_connection] ssh_executable = /usr/bin/ssh ```
Author
Owner

@marek22k commented on GitHub (Jan 10, 2023):

Reported in ansible, but closed: https://github.com/ansible/ansible/issues/79702

<!-- gh-comment-id:1377562919 --> @marek22k commented on GitHub (Jan 10, 2023): Reported in ansible, but closed: https://github.com/ansible/ansible/issues/79702
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#1014
No description provided.