Master SSH is enough

SSH is the standard configuration of every computer, and Linux needless to say, even Windows has its own OpenSSH since 2018.
Its main purpose is to log in to a remote computer to execute commands. In the era of cloud development, it is a tool that every program uses every day. This article will briefly introduce its principle,
basic usage and advanced usage such as port forwarding and dynamic forwarding.

Introduction

SSH is called Secure Shell Protocol ( S ecure Sh ell), which is an encrypted network transmission protocol that can provide a secure transmission environment for network services in an insecure network. It realizes the connection between SSH client and server by creating a secure tunnel in the network. In the earliest days, Internet communications were all plaintext communications. Once intercepted, the content would be exposed. In 1995, Finnish scholar Tatu Ylonen designed the SSH protocol to encrypt all login information and become a basic solution for Internet security. It has quickly been promoted throughout the world and has now become a standard configuration for all operating systems.

SSH is a protocol, and there are multiple implementations, both commercial implementations and open source implementations (OSSH, OpenSSH). The own software OpenSSH used in this article, after all, is currently the most popular SSH implementation, and it is the default component of all operating systems.

TIPS: History of OpenSSH Development
In July 1995, Tatu Ylonen released a set of programs for protecting information transmission (that is, SSH) in the form of free software. The program became popular quickly, and by the end of the year there were already 20,000 users in 50 countries. So at the end of the year, he founded the SSH Communication Security Company to continue to develop and sell SSH, so it became proprietary software. In 1999, Swedish programmers developed OSSH based on the last open source version of SSH, 1.2.12. After that, OpenBSD developers made a lot of modifications on the basis of OSSH to form OpenSSH. It is currently the only most popular SSH implementation and has become the default component of all operating systems.

Principle introduction

The reason why SSH has been developed rapidly as soon as it was proposed is that data security is very important to anyone. Here we explore the principle of protecting data security.

Before talking about encryption, let’s introduce some basic concepts of cryptography:

  • Plain text plaintextrefers to the readable information that the sender (generally refers to the client) wants the recipient (generally refers to the server) to obtain
  • Ciphertext ciphertextindicates the information generated after the text is encrypted
  • Secret key keyrefers to the cryptographic information used to complete cryptographic applications such as encryption, decryption, integrity verification, etc. It is a parameter required by the algorithm for converting plain text to cipher text or cipher text to plain text
  • Private key refers to private key
  • Public key refers to the public key

Symmetric encryption

Symmetric encryption means that the same secret key is used for encryption or decryption. Commonly used symmetric encryption algorithms are AES, DES, etc. The specific timing diagram is as follows:
ssh_symmetric.png

The advantages of symmetric encryption are high encryption and decryption efficiency and fast speed. For the server, it and each client must have a secret key. The large number of clients leads to a large number of secret keys. Once the machine is logged in, all secret keys are leaked. The disadvantage is the management of secret keys. It is difficult to distribute and not safe.

Asymmetric encryption

Asymmetric encryption requires a pair of secret keys to encrypt and decrypt. The public key is called the public key, and the private key is called the private key. Note that the information encrypted by the public key can only be unlocked by the private key (encryption process), and the information encrypted by the private key can only be unlocked by the public key (signature verification process). The more commonly used asymmetric encryption algorithm is RSA. The specific sequence diagram is as follows:
[The external link image transfer failed, the source site may have an anti-leech chain mechanism, it is recommended to save the image and upload it directly (img-hwRts4Zk-1610983782412)(https://blog.haojunyu.com/imgs/ ssh_asymmetric.png)]

The advantages of asymmetric encryption are higher security and convenient key management. Each server only needs to maintain a pair of public and private keys. The disadvantage is that encryption and decryption takes a long time and the speed is slow. But for modern computers, this cost is negligible.

Man in the middle attack

The full English name of man-in-the-middle attack is Man-in-the-middle attack, abbreviated as MITM. In the field of cryptography and computer security, it means that the attacker creates independent connections with both ends of the communication, and exchanges the data they receive, so that both ends of the communication think they are talking directly with each other through a private connection. But in fact the entire session is completely controlled by the attacker. In a man-in-the-middle attack, the attacker can intercept the conversation between the communicating parties and insert new content. In many cases this is very simple (for example, a man-in-the-middle attacker within the acceptance range of an unencrypted Wi-Fi wireless access point can insert himself as a middleman into the network). The specific sequence diagram is as follows:
[The external link image transfer failed, the source site may have an anti-leech chain mechanism, it is recommended to save the image and upload it directly (img-7CPMTMvx-1610983782413)(https://blog.haojunyu.com/imgs/ ssh_mitm.png)]

The key reason for the man-in-the-middle attack is that the client does not know the authenticity of the server's public key, and the server does not know the authenticity of the client's public key. So the key to cracking this question is how to authenticate each other, which is to prove that I am me and you are you as in Huang Hong's "Unlocking" sketch.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@  WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!   @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:sYNNR1L6T5cSAG4BndqtdDhJEI0eB9LamBTkuIue3+0.
Please contact your system administrator.
Add correct host key in /Users/xx/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/xx/.ssh/known_hosts:40
ECDSA host key for [xx.com] has changed and you have requested strict checking.
Host key verification failed.

Basic usage

Generate public key

ssh-keygen is a standard component of the Secure Shell (SSH) protocol suite for generating, managing and converting authentication keys.

Parameter Description

  • -b bits Specify the number of bits in the secret key to be created, the default is 2048 bits. The larger the value, the more complex the password
  • -C comment comment, at the end in id_rsa.pub
  • -t rsa/dsa, etc. specify the type of secret key to be created, the default is RSA
  • -f filename Specifies the name of the public and private key, will $HOME/.sshproduce a public key and a private key filename directory filename.pub
  • -N password specifies the password to use the secret key, which makes it more secure when multiple people use the same machine

Common commands

# 生成公私钥,默认文件为 ~/.ssh/id_rsa
ssh-keygen -t rsa -b 4096 -C "[email protected]"

Management key

ssh-agent and ssh-add are standard components of the Secure Shell (SSH) protocol suite for managing private keys. Under normal circumstances, we use id_rsa without password as our default private key. At this time, there is no need to start ssh-agent. We need it when we encounter the following two situations:

  1. When using different secret keys to connect to different hosts, you need to manually specify the corresponding secret key. (Ssh-agent helps us choose the corresponding secret key for authentication)
  2. When the private key is set with a password, and we need to frequently use the private key for authentication. (Ssh-agent helps us avoid re-entering the password)

Agent common commands

# 启动代理
eval `ssh-agent`
# 关闭代理
ssh-agent -k
# 在 ~/.bashrc 中加入以下来实现登陆自动启动 ssh-agent,退出自动 kill 掉程序
eval $(ssh-agent -s) > /dev/null
trap 'test -n "$SSH_AGENT_PID" && eval `/usr/bin/ssh-agent -k` > /dev/null' 0

# 查看代理中的私钥
ssh-add -l
# 查看代理中私钥对应的公钥
ssh-add -L
# 移除指定的私钥
ssh-add -d /path/of/key/key_name
# 移除所有的私钥
ssh-add -D

Send public key

ssh-copy-id is a script used to put the public key on the server. It landed remote server via SSH password and the public key into the remote server specified $HOME/.ssh/authorized_keysin. This operation is also possible to log in to the server, and then through the vi text editor such as command $HOME/.ssh/authorized_keysallows the public to join in the landing. However, for cloud servers, you can bind the public key on the page when you start the server, which is more secure (Alibaba Cloud and Tencent Cloud turn off secret key login by default PasswordAuthentication no). Pay special attention to that, never log in to the remote server through a password on a public network, and there is no problem with the secret key login.

# 发送公钥的两种方式(等价)
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host
ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

log in

Login configuration

SSH login server needs to know the server's host address (host name or host IP address), user name and password, and sometimes specify the port number (default 22). The host name is fine, but the host IP address is more difficult to remember, especially when you may have to log in to more than a dozen servers. Generally, the login commands we use are as follows:

# 登陆目标服务器( 172.17.132.120 )
ssh -p 58422 [email protected]
# 通过跳板机登陆目标服务器( 172.17.132.120 )
ssh -p 58422 [email protected] ssh [email protected]
# 端口映射
ssh -p 58422 [email protected] -fNL 5433:172.17.132.120:5432 -N

By configuring $HOME/.ssh/configyou can log in using the following command.

# 登陆目标服务器( 172.17.132.120 )
ssh target
# 通过跳板机登陆目标服务器( 172.17.132.120 )
ssh jump_target
# 端口映射
## 登陆时通过 LocalForward 配置
ssh jump_target
## 使用-L来实现本地端口映射
ssh -C -N -g -L 5433:127.0.0.1:5432 jump_target
# 通用配置,所有配置都使用
Host *
    AddKeysToAgent yes      # 将私钥添加到ssh-agent中
    UseKeychain yes         # 保存密码到agent中
    ServerAliveInterval 10  # 连接心跳间隔10s
    ServerAliveCountMax 3   # 重连次数为3
# target配置
Host target
    HostName 172.17.132.120
    User user
    Port 58422
    IdentityFile ~/.ssh/id_rsa
# 跳板机配置
Host jumper
    HostName jumper.example.com
    User user
    Port 58422
    IdentityFile ~/.ssh/id_rsa
Host jump_target
    HostName 172.17.132.120
    User user
    Port 22
    IdentityFile ~/.ssh/id_rsa
    ProxyCommand ssh user@jumper -W %h:%p 2>/dev/null
    LocalForward 5433 localhost:5432    # 本地5433映射到jump_target的5432

TIPS:
The Remote plug-in of VS Code will read the local configuration file $HOME/.ssh/configfor remote development like a local.

First login

In general $HOME/.sshdirectory in addition to public and private key files, configuration config file, the authorized_keys file authentication, there is a known_hosts file.
This file records the remote host ip and the corresponding public key fingerprint of the remote host. When we log in to the server for the first time (password or secret key login), there will be the following prompt interface:

### SSH 首次登陆的提示
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:HosOqhcUmbB7QG81yCuDPkvxTgot+vpple+czXPrEug.
ECDSA key fingerprint is MD5:fd:d7:e1:2c:42:4e:b4:2d:a3:21:4d:d1:c4:74:64:2d.
Are you sure you want to continue connecting (yes/no)?

At this time, known_hosts does not have the fingerprint information of the machine 127.0.0.1, so this prompt is displayed to let us confirm whether the fingerprint is the fingerprint of the ECDSA algorithm of the target machine.
When we enter yes to confirm, the next time we log in, the public key fingerprint sent by the remote host can be directly compared with the public key fingerprint of the corresponding ip in the known_hosts file.

# 本机查看服务器 172.17.132.120 的所有公钥(要与服务器上 /etc/ssh 下面的公钥 *.pub 一致)
ssh-keyscan -p 22 172.17.132.120

# 查看服务器公钥 ecdsa 的指纹 -E md5/sha256 指纹 hash 算法
ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ecdsa_key.pub
## 256 MD5:84:3d:9c:6e:75:f2:6b:b2:0b:40:aa:d6:29:2f:b4:40 no comment (ECDSA)
## 256 SHA256:ZoGnph63gnKLC9wQYrHYVU8ROTf6+K9LKAjn+jrXB2o no comment (ECDSA)

# 从客户端查看服务器公钥 ecdsa 的指纹(初次登陆时要验证的指纹)
ssh-keyscan -t ecdsa -p 22 172.17.132.120 |ssh-keygen -lf -

# 公钥转换成特定指纹 hash 算法的指纹
awk '{print $2}' /etc/ssh/ssh_host_ecdsa_key.pub | base64 -d|openssl sha256 -binary |base64

TIPS: The importance of
known_hosts known_hosts This file is an important basis for the client to verify the identity of the server. Every time a client initiates a connection request to the server, not only the server needs to verify the legitimacy of the client, but the client also needs to verify the identity of the server. The client verifies whether the server has changed through the fingerprint of the public key in known_hosts. It can avoid man-in-the-middle attacks to a certain extent, except for the first login, because there is no server identity information in known_hosts at that time, so the first login fingerprint information needs to be compared with the server. The safest way is to log in with the secret key the first time you log in.

Login process

  1. Version number negotiation phase
  2. Key and algorithm negotiation stage The
    server and the client respectively send algorithm negotiation messages to each other. The messages include the list of public key algorithms, encryption algorithms, message verification code algorithms, and compression algorithms they support. The server and the client derive the final algorithm to be used according to the algorithm supported by each other and themselves. The server and the client use the DH exchange algorithm, host key pair and other parameters to generate the session key and session ID.
  3. Authentication phase (publickey> gssapi-keyex> gssapi-with-mic> password)
  4. Session request phase
  5. Session interaction phase

Password login

The authentication process for password login is as follows:

  1. The client uses the key and the session key generated in the algorithm negotiation stage to encrypt the account, authentication method, and password, and sends the result to the server.
  2. The server uses the obtained session key to decrypt the message to obtain the account and password.
  3. The server judges the account and password, and if it fails, it sends an authentication failure message to the client, which contains a list of methods that can be authenticated again.
  4. The client selects a method from the list of authentication methods for re-authentication.
  5. This process is repeated until the authentication succeeds or the number of authentication times reaches the upper limit, and the server closes this TCP connection.

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-b82zsAeS-1610983782414)(https://blog.haojunyu.com/imgs/ssh_password.png)]

Secret key login

The authentication process for key login is as follows:

  1. The client uses the key and the session key generated in the algorithm negotiation phase to encrypt the account, authentication method, id_rsa.pub, and sends the result to the server.
  2. The server uses the session key to decrypt the message to get the account number and id_rsa.pub. In the server $HOME/.ssh/authorized_keysto find the corresponding public key, if not found, a failure message is sent to the client, if found, compare the customer sent by the public and the public to find, if the content is the same, the server generates a random string , Referred to as "challenge", then use the found public key to encrypt the challenge, and then use the session key to encrypt again.
  3. The server sends this double-encrypted data to the client
  4. The client uses the session key to decrypt the message, and then uses id_rsa to decrypt the data again to get the challenge.
  5. The client uses the session key to encrypt the challenge and sends it to the server.
  6. The server uses the session key to decrypt the message, gets the challenge, and determines whether it is the one generated by it. If it is not the same, it sends a failure message to the client. If it is the same, the authentication is passed.

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-39UMB4LL-1610983782415)(https://blog.haojunyu.com/imgs/ssh_key.png)]

The difference between the two

We often say that logging in with a secret key is more convenient and safer than logging in with a password. Why do you say that? The convenience is because there is no need to remember the password. Security is that on the one hand, the sensitive and key password is not being transmitted, and on the other hand, because the existence of the challenge makes the client and server authenticated in a conversation.

Advanced usage

Password-free secure transmission

Both scp/rsync/sftp can be used for secret-free and secure transmission based on SSH. Common commands are as follows:

# 从本地同步 src.tar.gz 文件到远程服务器 jump_target 的目录 /path/to/des/
scp src.tar.gz jump_target:/path/to/des/
rsync -avz src.tar.gz jump_target:/path/to/des/

# 从远程服务器 jump_target 的文件 /path/to/src.tar.gz 到本地
scp jump_target:/path/to/src.tar.gz .
rsync -avz jump_target:/path/to/src.tar.gz .

Port forwarding

SSH can not only automatically encrypt and decrypt the network data between the SSH client and server, but at the same time, SSH can also provide a very useful function, which is port forwarding, that is, forwarding the network data of the TCP port to the specified host On a certain port, the data will be encrypted and decrypted accordingly while forwarding. If the firewall in the working environment restricts the use of some network ports, but allows SSH connections, then it is also possible to communicate by using the SSH forwarded port. Forwarding is mainly divided into two types: local forwarding and remote forwarding.

Forward common parameters

  • -C: Compress transmission, increase transmission speed.
  • -f: transfer SSH transmission to the background for execution, without occupying the current SHELL, often used with -N
  • -N: Establish a silent connection (a connection is established but no specific session can be seen)
  • -g: In the -L/-R/-D parameter, the remote host is allowed to connect to the established forwarding port. If this parameter is not added, only the local host is allowed to establish a connection.
  • -L: local port forwarding
  • -R: remote port forwarding
  • -D: dynamic forwarding (SOCKS proxy)
  • -P: Specify SSH port

Local port forwarding

The port A of the local web server is forwarded to port B of the remote server. To put it bluntly, the request sent to the local port A is forwarded to the target port B. The format is as follows

ssh -L 本地网卡地址:本地端口:目标地址:目标端口 用户@目标地址
The common application scenarios are shown in the figure below:
[External link image transfer failed, the origin site may have anti-leeching mechanism, it is recommended to save the image and upload it directly (img-YGEv3GsP-1610983782416)(https://blog.haojunyu.com/imgs /ssh_local.png)]

The corresponding commands are as follows:

# jump_target 服务器上的 3306 端口服务映射到本地 33306 `mysql -u root -p root -H localhost -P 33306`
## 1 是 2,3,5 路线中的加密通道,将本地 33306 的网络数据转发到 jump_target 的 3306 端口
ssh -C -N -g -L 33306:localhost:3306 jump_target
## 在 2,3 中搞了个加密通道,然后在跳板机上将本地 33306 的网络数据转发到 172.17.132.120 的 3306 端口
ssh -C -N -g -L 33306:172.17.132.120:3306 jumper

Remote port forwarding

A port of the remote server is forwarded to a port of the server on the local network. To put it plainly, it means forwarding the request sent to the remote port to the target port. The format is as follows:

ssh -R 远程网卡地址:远程端口:目标地址:目标端口 用户@目标地址
Common application scenarios have a special term called intranet penetration, and the structure is as shown in the following figure:
[External link image transfer fails, the source site may have an anti-theft chain mechanism, it is recommended to save the image and upload it directly (img-OVntmvD5-1610983782417)(https ://blog.haojunyu.com/imgs/ssh_remote.png)]

# 将公网上的服务器 jump_target 的端口 33333 映射到本地的 22,这样就可以通过在 jump_target 上通过 SSH 来访问本地机器
ssh -f -N -g -R 33333:127.0.0.1:22 jump_target

TIPS:
The jump_target of the server on the public network should be set GatewayPorts yes, the default is no. In addition, the port 33333 to be mapped must be accessible.

Dynamic forwarding

Dynamic forwarding is to establish an SSH encrypted SOCKS 4/5 proxy channel. Any program that supports the SOCKS 4/5 protocol can use this encrypted channel for access. The format is as follows:
ssh -D [本地地址:]本地端口号 远程用户@远程地址

# 将访问本地 55558 端口的请求都转发给 jump_target ,并让它去执行
ssh -C -N -g -T -D 127.0.0.1:55558 jump_target

Daily use problems

Springboard configuration

# 跳板机的配置
Host jump
  HostName  jumper.example.com
  Port      58422
  User      haojunyu
  IdentityFile ~/.ssh/dg_rsa
  AddKeysToAgent yes    # 将私钥添加到 agent 中
  UseKeychain yes       # 保存密码到 agent 中
# 目标机的配置
Host ws
  HostName  172.17.132.120
  Port      22
  User      haojunyu
  IdentityFile ~/.ssh/dg_rsa
  ProxyCommand ssh haojunyu@jump -W %h:%p 2>/dev/null
  ServerAliveInterval 10
  ServerAliveCountMax 3

Any service access on the intranet

In daily work, many services are often started on the internal network machine, and then the local port is mapped to the service port on the internal network machine through hole drilling (local port forwarding).
The problem is that a service must maintain a hole punch command ssh -C -N -g -L 33306:172.17.132.120:3306 jumper.
To deal with such problems, the best solution is to use dynamic forwarding ssh -C -N -g -T -D 127.0.0.1:55557 hb_jumper, and
use SwitchyOmega or proxifier tools to forward requests for the intranet IP segment 172.17.* to the local port 55557.

git push report permission not allowed (public key)

Usually executed on the server git pushwill be reported the following error

Specific error message:
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

The reason for the error is that there is no service on the current machine to tell git which private key to use for git operations.
There are many corresponding solutions, and solutions one and two are recommended:

  • Solution one: ~/.ssh/configspecified (applicable individual machines)

    Host github.com
        HostName  github.com
        User      haojunyu
        IdentityFile ~/.ssh/id_rsa
    
  • Solution 2: Configure the warehouse or global core.sshCommand (the designated warehouse applies to shared machines, and the global applies to personal machines. The git version is higher than 2.3.0 )

    git config core.sshCommand "ssh -i ~/.ssh/id_rsa -F /dev/null"
    
  • Solution 3: ssh-agent temporary authorization (applicable to shared machines)

    eval `ssh-agent`
    ssh-add ~/.ssh/id_rsa
    

Servicing of port forwarding commands

In this case, it is hoped that the port forwarding will be enabled when the machine is turned on, and it has been maintained. This has to introduce two commonly used servicing tools in linux: Supervisor and Systemd.
The former requires Supervisor to be installed, but the tools are lighter and easier to use. The latter is heavier, but basically all systems come with it. The configuration methods for both are provided below:

  • Supervisor configuration
[program:ssh-wifi_ol]
command=ssh -C -N -g -L 9789:127.0.0.1:9789 jump
stdout_logfile=/Users/haojunyu/.supervisord_log/ssh-wifi_ol.log
autostart=true
autorestart=true
startsecs=5
priority=1
stopasgroup=true
killasgroup=true
  • Systemd configuration
# gfw service
[Unit]
Description=gfw
After=network.target
[Service]
Type=simple
User=hjy
ExecStart=ssh -C -N -g -T -D 127.0.0.1:55558 gfw
Restart=on-failure
[Install]
WantedBy=multi-user.target

TIPS:
Some frequently used services are serviced through port forwarding, and some temporary services are port forwarded through commands. You can also use port forwarding Python programs written by colleagues.

references

  1. What is SSH? You should have used it
  2. Wikipedia-SSH
  3. windows supports openssh
  4. Graphical SSH principle
  5. SSH official documentation
  6. All pictures
  7. Man in the middle attack
  8. Understanding ssh proxy
  9. What is the key fingerprint in ssh remote login and how to compare
  10. Detailed explanation of ssh login authentication process

If this article has helped you, or if you are interested in technical articles, you can follow the WeChat public account: Technical Tea Party, you can receive related technical articles as soon as possible, thank you!
Technical tea party

This article is automatically published by ArtiPub , a multi- posting platform

Guess you like

Origin blog.csdn.net/haojunyu2012/article/details/112797471
ssh