Skip to content

Add bastion user option #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- "8"
- "12"

services:
- docker
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@ await sshConnection.forward({
})
```

#### Port forwarding and using a bastion/jump host with different user to jump host and end host

```sh
$ ssh -L 9000:localhost:80 -J [email protected] example.com
```

```js
const sshConnection = new SSHConnection({
endHost: 'example.com',
bastionHost: 'your-jump-host.com',
bastionUsername: 'your-jump-user'
})
await sshConnection.forward({
fromPort: 9000,
toPort: 80,
})
```

#### Executing a command on the remote server

```js
Expand All @@ -94,6 +112,8 @@ Options are an object with following properties:
* `endHost` (required): The host you want to end up on (connect to)
* `endPort` (optional): Port number of the server. Needed in case the server runs on a custom port (defaults to `22`)
* `bastionHost` (optional): You can specify a bastion host if you want
* `bastionUsername` (optional): You can specify the bastion username if you want, in case it is different from the user connecting to end host.
If not provided while bastionHost is specified, connection will fall back to the username.
* `passphrase` (optional): You can specify the passphrase when you have an encrypted private key. If you don't specify the passphrase and you use an encrypted private key, you get prompted in the command line.
* `noReadline` (optional): Don't prompt for private key passphrases using readline (eg if this is not run in an interactive session)

Expand Down
3 changes: 2 additions & 1 deletion src/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface Options {
privateKey?: string | Buffer
agentForward? : boolean
bastionHost?: string
bastionUsername?: string
passphrase?: string
endPort?: number
endHost: string
Expand Down Expand Up @@ -151,7 +152,7 @@ class SSHConnection {
const options = {
host,
port: this.options.endPort,
username: this.options.username,
username: (this.options.bastionHost && host === this.options.bastionHost && this.options.bastionUsername) ? this.options.bastionUsername : this.options.username,
password: this.options.password,
privateKey: this.options.privateKey
}
Expand Down
2 changes: 1 addition & 1 deletion test/bastion-host/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ RUN apt-get -yq install openssh-server; \
mkdir /root/.ssh && chmod 700 /root/.ssh; \
touch /root/.ssh/authorized_keys

COPY ./server/sshd_config /etc/ssh/sshd_config
COPY ./bastion-host/sshd_config /etc/ssh/sshd_config


COPY ./keys/authorized_keys /root/.ssh/authorized_keys
Expand Down
20 changes: 20 additions & 0 deletions test/bastion-host/DockerfileDiffUser
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM ubuntu:16.04

RUN apt-get update
RUN apt-get -yq install openssh-server; \
mkdir -p /var/run/sshd; \
useradd -r -m bastionUser; \
cd /home/bastionUser; \
mkdir ./.ssh && chmod 700 ./.ssh; \
touch ./.ssh/authorized_keys

COPY ./bastion-host/sshd_config_diffUser /etc/ssh/sshd_config

COPY ./keys/authorized_keys /home/bastionUser/.ssh/authorized_keys

RUN cd /home/bastionUser/.ssh; \
chgrp -R bastionUser ./; \
chown -R bastionUser ./

EXPOSE 22 23
CMD /usr/sbin/sshd -D -p 22 -p 23
86 changes: 86 additions & 0 deletions test/bastion-host/sshd_config_diffUser
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
AllowUsers bastionUser

RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
#Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
7 changes: 4 additions & 3 deletions test/client/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ RUN yarn build

# adds the ssh keys
COPY ./test/keys /root/.ssh/
COPY ./test/keys /home/bastionUser/.ssh/

# add the non protected key as the standard key
COPY ./test/keys/id_rsa_no_pass /root/.ssh/id_rsa
COPY ./test/keys/id_rsa_no_pass /home/bastionUser/.ssh/id_rsa
COPY ./test/keys/id_rsa_no_pass.pub /root/.ssh/id_rsa.pub

COPY ./test/keys/id_rsa_no_pass.pub /home/bastionUser/.ssh/id_rsa.pub

# COPY ./dist ./dist
COPY ./test ./test


CMD ["yarn", "test"]
CMD ["yarn", "test"]
7 changes: 7 additions & 0 deletions test/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ services:
build:
context: ./
dockerfile: ./bastion-host/Dockerfile

bastion-different-user:
ports:
- 22:22
build:
context: ./
dockerfile: ./bastion-host/DockerfileDiffUser

tester:
build:
Expand Down
18 changes: 18 additions & 0 deletions test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,23 @@ describe('node-ssh-forward', async () => {
})
await ssh.executeCommand('uptime')
})
it('with root as bastion user and default path to the private key', async () => {
const ssh = new SSHConnection({
username: 'root',
endHost: 'server',
bastionHost: 'bastion',
bastionUsername: 'root'
})
await ssh.executeCommand('uptime')
})
it('with bastionUser as bastion user and default path to the private key', async () => {
const ssh = new SSHConnection({
username: 'root',
endHost: 'server',
bastionHost: 'bastion-different-user',
bastionUsername: 'bastionUser'
})
await ssh.executeCommand('uptime')
})
})
})