Change default SSH settings for remote host
Update .ssh/config
Host <host>
port <new_port>
user <new_user>
IdentityFile <new_file>
.ssh/config
Host <host>
port <new_port>
user <new_user>
IdentityFile <new_file>
~/.ssh/config
Add option to specific host for login user.
Host server_names
StrictHostKeyChecking no
/etc/ssh/ssh_config
This is to set for all servers and all users
StrictHostKeyChecking no
List down the commands required.
export VAULT_ADDR='https://vault.bx.net:8200'
export VAULT_TOKEN="<ROOT_TOKEN>"
vault token create -field token -policy=ssh-admin-policy
export VAULT_TOKEN="<SSH_ADMIN_TOKEN>"
vault token renew
export VAULT_TOKEN="<SSH_ADMIN_TOKEN>"
vault token lookup
vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@$HOME/.ssh/id_rsa.pub > ~/.ssh/signed-cert.pub
ssh -i ~/.ssh/signed-cert.pub -i ~/.ssh/id_rsa <host>
export VAULT_ADDR='https://vault.bx.net:8200'
export VAULT_TOKEN="<ROOT_TOKEN>"
vault read -field=public_key ssh-client-signer/config/ca > /etc/ssh/trusted-user-ca-keys.pem
/etc/ssh/sshd_config
Add following lines in /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
CASignatureAlgorithms ^ssh-rsa
Note: Comment out last line if SSH got error
The SSL cert in vault server needs to be trusted by local client, otherwise, following server occurred.
Error writing data to ssh-client-signer/sign/my-role: Put "<role_name>": x509: certificate signed by unknown authority
This is required if host key replaced in target server.
ssh-keygen -R HOSTNAME
ssh-keygen -R IP_ADDRESS
When access remote servers, proxy server/jump host could be a good choice.
This is the proxy server, normally can be in the form of user@proxy_host
.
This is the target server, has the form of target_user@target_host
.
This is the most simplest method which uses remote ssh command to login to target server. If just wants to use one SSH server to access another SSH server, run following command
ssh -t <jump_host> ssh <target>
Here -t
is to create a pseudo-terminal, otherwise, the remote server could not display message because no tty can be used.
This is using SSH building proxy function.
ssh -o "ProxyJump <jump_host>" <target>
This is to run an external command to build communication. For example, use nc
command, and pass two parameters, %h
is the target host, %p
is the port.
ssh -o "ProxyCommand ssh <jump_host> nc %h %p" <target>
./ssh/cofig
Instead of using command, ProxyJump
and ProxyCommand
can be set in ssh client configuration file.
Host <connection_name>
HostName <target_host>
User <target_user>
ProxyCommand ssh <jump_host> nc %h %p
Host target
HostName 192.168.1.2
User user1
ProxyCommand ssh user2@proxy nc %h %p
Host * !proxy
HostName %h
User target_user
# ProxyCommand ssh proxy_user@proxy nc %h %p
/etc/ssh/ssh_config
This is the same as previous example, except it is a global setting.
Except User name and Password, which is hard to remember if you don't want others guess it easily, there are other easy ways to protect SSH server.
This is most a simple way, just generate a pair of key,
ssh-keygen
If need more secure, generate 4096 bit RSA key
ssh-keygen -t rsa -b 4096
Then inject public key in .ssh/id_rsa.pub
into remote .ssh/authorized_keys
Refer to Signed SSH Certificates using Hashicorp Vault in Practice
Use free software, hashicorp vault to manage signed certificate.
Inject trusted CA key retrieved from vault into target SSH server configure,
Use authorized token and client private key to generate short life signed certificate
Use signed certificate and client private key login to target server
Note: Only need normal token to generate signed certificate
Need to save a token
Refer to Enable 2FA for Ubuntu
Instead of all servers maintain their own password, passwords are centrally managed by authentication server.
Retrieve password from authentication server, then use it to login to remote server.
Remote server will use it to verify against authentication server.
As suggested, root token should not be used, and it should be revoked immediately after used.
Follow the steps in page below to create a new root token and revoke it after used.
Generate a new root token for Hashicorp Vault
For example, SSH secret engine, following admin policy can be created
vault policy write ssh-admin-policy - << EOF
# SSH secret engine
path "ssh-client-signer/sign/*" {
capabilities = ["create", "read", "update", "delete", "sudo", "list" ]
}
# Mount the AppRole auth method
path "sys/auth/approle" {
capabilities = [ "create", "read", "update", "delete", "sudo" ]
}
# Configure the AppRole auth method
path "sys/auth/approle/*" {
capabilities = [ "create", "read", "update", "delete" ]
}
# Create and manage roles
path "auth/approle/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Write ACL policies
path "sys/policies/acl/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
##### Add other requirement if required. For example
# Write test data
# Set the path to "secret/data/mysql/*" if you are running `kv-v2`
path "secret/mysql/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
EOF
Then create token under this policy
vault token create -field token -policy=ssh-admin-policy
The using this token follow the steps in page below:
Signed SSH Certificates using Hashicorp Vault in Practice
To get renew token before expired, run following command
vault token renew
The expire time can be view using following command
vault token lookup
In previous setup, root token is used all the time, which should not be the case in real situation.
The steps can follow Signed SSH Certificates using Hashicorp Vault
export VAULT_TOKEN=<root_token>
export VAULT_ADDR='http://host:8200'
$ vault policy write my-policy - << EOF
path "ssh-client-signer/sign/my-role" {
capabilities = ["create", "update", "read"]
}
EOF
$ vault token create -field token -policy=my-policy
$ export VAULT_TOKEN="<policy_token>"
$ vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
ssh -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@host
vault auth enable approle
vault write auth/approle/role/my-role \
secret_id_ttl=10m \
token_num_uses=10 \
token_ttl=20m \
token_max_ttl=30m \
secret_id_num_uses=40 \
token_policies=my-policy
vault read -field=role_id auth/approle/role/my-role/role-id
vault write -f -field=secret_id auth/approle/role/my-role/secret-id
export VAULT_ADDR='http://host:8200'
export ROLE_ID=<role_id>
export SECRET_ID=<secret_id>
vault write auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID"
Result contains token
Key Value
--- -----
token s.Sh9h1wZ9ycATeSaASoOQvovr
...
vault token lookup | grep policies
policies [default my-policy]
$ export VAULT_TOKEN="<policy_token>"
$ vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
ssh -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@host
If tested finished, password authentication can be set to no:
PasswordAuthentication no
If the secret_id expires so fast, then needs to have master token to generate secret_id again, because the policy token is generated using role_id and secret_id pair.
If don't use approle, then all SSH clients can use policy token. Still thinking the advantage of using role_id and secret_id.
The root token should not be used as recommended. Will try admin token later.
The idear of signed SSH certificates verification is to use valid (signed) SSH certificate to be verified by SSH server or by SSH client, or by both.
Client retrieves signed public key which issued by the CA key in Vault. This key has short expiry date.
Server uses the CA public key configured in SSH configuration, validates the client public key issued by Vault.
This is to validate server public whether signed by Vault by place public key in .ssh/known_hosts
file. This key should have long expiry date.
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN="<token>"
$ vault secrets enable -path=ssh-client-signer ssh
Successfully mounted 'ssh' at 'ssh-client-signer'!
$ vault write ssh-client-signer/config/ca generate_signing_key=true
Key Value
--- -----
public_key ssh-rsa AAAAB3NzaC1yc2EA...
Beware of *allowed_users" and "default_user", they must be set correctly.
$ vault write ssh-client-signer/roles/my-role -<<"EOH"
{
"allow_user_certificates": true,
"allowed_users": "*",
"allowed_extensions": "permit-pty,permit-port-forwarding",
"default_extensions": [
{
"permit-pty": ""
}
],
"key_type": "ca",
"default_user": "ubuntu",
"ttl": "30m0s"
}
EOH
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN="<token>"
# vault read -field=public_key ssh-client-signer/config/ca > /etc/ssh/trusted-user-ca-keys.pem
Add following lines in /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
# systemctl restart sshd
$ ssh-keygen -t rsa -C "user@example.com"
This will generate a pair of files, .ssh/id_rsa
and .ssh/id_rsa.pub
.
$ vault write -field=signed_key ssh-client-signer/sign/my-role \
public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
This can verify the valid period and user
$ ssh-keygen -Lf ~/.ssh/signed-cert.pub
...
Valid: from 2021-11-27T17:51:29 to 2021-11-27T18:21:59
Principals:
ubuntu
...
$ ssh -i signed-cert.pub -i ~/.ssh/id_rsa username@10.0.23.5
Note: Add following configure in /etc/ssh/sshd_config
if got error __userauth_pubkey: certificate signature algorithm ssh-rsa: signature algorithm not supported [preauth]__
CASignatureAlgorithms ^ssh-rsa
Signed SSH Certificates
Leveraging Signed SSH for Remote Access with Vault