Skip to content
This repository has been archived by the owner on Jan 17, 2021. It is now read-only.

Add SSH master connection feature #116

Merged
merged 8 commits into from
Jun 28, 2019
Merged

Conversation

deansheather
Copy link
Member

@deansheather deansheather commented Jun 12, 2019

By default, sshcode will now start a master connection with no command so that users only need to authenticate once and multiple connections don't need to be established. This speeds up load times significantly as there are less handshakes required. Currently, it requires you to enter your password or SSH key passphrase 4 times (6 times with sync back) unless you are using an agent.

To disable the added behaviour you can use --no-reuse-connection.

You can do this now on the current sshcode version by doing --ssh-flags '-o "ControlPath=/tmp/test" -o "ControlMaster=auto" -o "ControlPersist=5m"', but this will keep SSH connections open after sshcode exits which likely isn't desired.

Closes #115.

TODO:

  • Test in more environments
  • Make checkSSHMaster() also check if the master process is dead in check
  • Automatically disable if ~/.ssh doesn't exist (and maybe if it's permissions aren't safe)

By default, sshcode will now start a master connection with no command
so that users only need to authenticate once and multiple connections
don't need to be established. This speeds up load times significantly as
there are less handshakes required.

To disable this behaviour you can use `--no-reuse-connection`.
sshcode.go Outdated Show resolved Hide resolved
@sumanthratna
Copy link

I tried running this on my MacOS Mojave, and it didn't work. I still had to log in 4 times. Here's what I did:

cd /tmp
git clone git@github.com:cdr/sshcode.git
git checkout -b reuse-ssh-connection
rm $GOPATH/bin/sshcode
go clean
go build
go install
sshcode <ssh alias>

@deansheather
Copy link
Member Author

@sumanthratna Does sshcode --ssh-flags '-o "ControlPath=/tmp/test" -o "ControlMaster=auto" -o "ControlPersist=5m"' host work by any chance?

- Replace the `ssh -O exit` tidyup command with just a SIGTERM on the
  master
- Add `exec` to the front of the SSH master cmd so it replaces the `sh`
  process (so we can send SIGTERM to it easier)
Checks if the master process is running by sending signal 0 to it.
According to kill(2), sending a signal of 0 will send no signal but will
still perform error checking.

To prevent the SSH master from becoming a zombie process, a wait call
was added in a goroutine.
@sumanthratna
Copy link

@sumanthratna Does sshcode --ssh-flags '-o "ControlPath=/tmp/test" -o "ControlMaster=auto" -o "ControlPersist=5m"' host work by any chance?

It does, so I guess I could set up a zsh alias for convenience. However, I still think this PR should be implemented.

@deansheather
Copy link
Member Author

The changes I've made are a more robust version of the ssh-flags thing. That flag will leave SSH commands behind for 5 minutes after sshcode exits.

I'd be interested in working out what the problem is with Mac, but I don't have one that I can test on.

Could you try (with the released version of sshcode) opening a terminal and running ssh -MNo "ControlPath=~/.ssh/control-%h-%p-%r" host and authenticating (it will not open a prompt on the remote server). Then, in a new terminal, could you run sshcode --ssh-flags 'ControlPath=~/.ssh/control-%h-%p-%r' host. To tidy up, just close sshcode and the first ssh connection.

The first process acts as the connection to the server, and all of the other ones should connect through it if it works properly. If that doesn't work, could you try with a different ControlPath (like /tmp/test)?

@sumanthratna
Copy link

sumanthratna commented Jun 15, 2019

2019-06-15 10:55:07 INFO	ensuring code-server is updated...
could not connect to remote: dial tcp 92.242.140.21:22: connect: operation timed out
ssh_exchange_identification: Connection closed by remote host
2019-06-15 10:56:23 FATAL	error: failed to update code-server: 
---ssh cmd---
ssh ControlPath=~/.ssh/control-%h-%p-%r tj '/usr/bin/env bash'
---download script---
set -euxo pipefail || exit 1

pkill -f ~/.cache/sshcode/sshcode-server || true
mkdir -p ~/.local/share/code-server ~/.cache/sshcode
cd ~/.cache/sshcode
wget -N https://codesrv-ci.cdr.sh/latest-linux
[ -f ~/.cache/sshcode/sshcode-server ] && rm ~/.cache/sshcode/sshcode-server
ln latest-linux ~/.cache/sshcode/sshcode-server
chmod +x ~/.cache/sshcode/sshcode-server: exit status 255

That's the output when I run the second command. tj is the host.

The normal sshcode command works though (but still asks for my password multiple times).


I tried using /tmp/test as the control path and I got:

2019-06-15 10:59:40 INFO	ensuring code-server is updated...
could not connect to remote: dial tcp: lookup controlpath=/tmp/test: no such host
ssh_exchange_identification: Connection closed by remote host
2019-06-15 10:59:40 FATAL	error: failed to update code-server: 
---ssh cmd---
ssh ControlPath=/tmp/test tj '/usr/bin/env bash'
---download script---
set -euxo pipefail || exit 1

pkill -f ~/.cache/sshcode/sshcode-server || true
mkdir -p ~/.local/share/code-server ~/.cache/sshcode
cd ~/.cache/sshcode
wget -N https://codesrv-ci.cdr.sh/latest-linux
[ -f ~/.cache/sshcode/sshcode-server ] && rm ~/.cache/sshcode/sshcode-server
ln latest-linux ~/.cache/sshcode/sshcode-server
chmod +x ~/.cache/sshcode/sshcode-server: exit status 255

@deansheather
Copy link
Member Author

Could you show me the exact command you used? It shouldn't be trying to dial it as a TCP host if it has the -o flag before it.

@deansheather
Copy link
Member Author

deansheather commented Jun 15, 2019

@sumanthratna Oh wait, my bad. This is totally my mistake. The sshcode command should be sshcode --ssh-flags '-o "ControlPath=~/.ssh/control-%h-%p-%r"' host. I forgot to add the -o.

Checks:
- if it exists
- if it's a directory (if not warn and disable reuse connection feature)
- if it has safe permissions (not writable by anyone except the owner,
  if not then warn)
@deansheather deansheather marked this pull request as ready for review June 15, 2019 17:16
@deansheather
Copy link
Member Author

This needs to be tested in more environments before being merged.

@deansheather deansheather requested a review from sreya June 15, 2019 17:17
@sumanthratna
Copy link

Adding the -o flag worked. However, in the terminal where I ran the ssh command (the first command), channel 4: open failed: connect failed: Connection refused is printed repeatedly. This doesn't interfere with functionality though.

@deansheather
Copy link
Member Author

It's strange that this branch doesn't work then, since what I told you to do is basically what this branch does for you.

The connect failed stuff is just the check for whether code-server is ready yet. sshcode just loops connecting to code-server over HTTP until it gets a reply, and the SSH TCP tunnel will print that error if nothing is listening on the other side yet.

@sumanthratna
Copy link

I just tried again, and it worked! Originally, I didn't remove the current sshcode source from my $GOPATH and I may have git-checkouted incorrectly.

Here's the output:

<ASKS FOR PASSWORD>
2019-06-18 13:23:36 INFO	ensuring code-server is updated...
+ pkill -f /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode/sshcode-server
+ true
+ mkdir -p /afs/csl.tjhsst.edu/students/2022/2022sratna/.local/share/code-server /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode
+ cd /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode
+ wget -N https://codesrv-ci.cdr.sh/latest-linux
--2019-06-18 13:23:15--  https://codesrv-ci.cdr.sh/latest-linux
Resolving codesrv-ci.cdr.sh (codesrv-ci.cdr.sh)... 2606:4700:30::681b:851a, 2606:4700:30::681b:841a, 104.27.132.26, ...
Connecting to codesrv-ci.cdr.sh (codesrv-ci.cdr.sh)|2606:4700:30::681b:851a|:443... failed: Network is unreachable.
Connecting to codesrv-ci.cdr.sh (codesrv-ci.cdr.sh)|2606:4700:30::681b:841a|:443... failed: Network is unreachable.
Connecting to codesrv-ci.cdr.sh (codesrv-ci.cdr.sh)|104.27.132.26|:443... connected.
HTTP request sent, awaiting response... 304 Not Modified
Cookie coming from codesrv-ci.cdr.sh attempted to set domain to cdr.sh
File 'latest-linux' not modified on server. Omitting download.

+ '[' -f /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode/sshcode-server ']'
+ rm /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode/sshcode-server
+ ln latest-linux /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode/sshcode-server
+ chmod +x /afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/sshcode/sshcode-server
2019-06-18 13:23:40 INFO	syncing settings
building file list ... done

sent 192 bytes  received 20 bytes  141.33 bytes/sec
total size is 172032  speedup is 811.47
2019-06-18 13:23:41 INFO	synced settings in 266.41042ms
2019-06-18 13:23:41 INFO	syncing extensions
building file list ... done

sent 76 bytes  received 20 bytes  192.00 bytes/sec
total size is 0  speedup is 0.00
2019-06-18 13:23:41 INFO	synced extensions in 391.765153ms
2019-06-18 13:23:41 INFO	starting code-server...
2019-06-18 13:23:41 INFO	Tunneling remote port 10334 to 127.0.0.1:50874
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
(node:29368) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
channel 3: open failed: connect failed: Connection refused
INFO  code-server v1.1119-vsc1.33.1
INFO  Additional documentation: http://github.com/cdr/code-server
INFO  Initializing {"data-dir":"/afs/csl.tjhsst.edu/students/2022/2022sratna/.local/share/code-server","extensions-dir":"/afs/csl.tjhsst.edu/students/2022/2022sratna/.local/share/code-server/extensions","working-dir":"/afs/csl.tjhsst.edu/students/2022/2022sratna","log-dir":"/afs/csl.tjhsst.edu/students/2022/2022sratna/.cache/code-server/logs/20190618172319151"}
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
channel 3: open failed: connect failed: Connection refused
INFO  Starting webserver... {"host":"127.0.0.1","port":"10334"}
channel 3: open failed: connect failed: Connection refused
WARN  No certificate specified. This could be insecure.
WARN  Documentation on securing your setup: https://github.com/cdr/code-server/blob/master/doc/security/ssl.md
WARN  Launched without authentication.
INFO   
INFO  Started (click the link below to open):
INFO  http://localhost:10334/
INFO   
INFO  Starting shared process [1/5]...
WARN  stderr {"data":"(node:29383) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.\n"}
INFO  WebSocket opened / {"client":1,"ip":"127.0.0.1"}
Error: ENOENT: no such file or directory, open '/src/packages/server/build/web/favicon.ico'
INFO  Connected to shared process

Everything looks okay, but there's that channel 3 output. It'd be nice if that part of the output could be muted somehow, but other than that, I think this can be merged.

sshcode.go Outdated Show resolved Hide resolved
main.go Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
sshcode.go Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
sshcode.go Outdated Show resolved Hide resolved
@deansheather
Copy link
Member Author

@sumanthratna I've fixed the connection failed log spam by telling the master to be quiet with -q.

@sumanthratna
Copy link

It works great, I think this can be merged.

@deansheather deansheather merged commit 2693c3f into master Jun 28, 2019
@deansheather deansheather deleted the reuse-ssh-connection branch June 28, 2019 00:17
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Password is asked for multiple times
3 participants