Skip to content
Update ssh authored by umaumax's avatar umaumax
[[_TOC_]]
## 設定ファイル
### `~/.ssh/config`
#### ProxyJump
[多段SSHならProxyJump!さよならProxyCommand | にっしーラボ](https://nissy-lab.com/blogs/multiple-ssh-proxyjump/)
#### sshの接続先の名称で処理を振り分けたい
[SSHのDynamic Forwardを気軽に使うTIPS \| Zenn]( https://zenn.dev/hnw/articles/36e70c0980c8786c7154 )
#### [sshをproxy経由でつなぐ \- @znz blog]( https://blog.n-z.jp/blog/2018-08-12-ssh-over-proxy.html )
[SSHのDynamic Forwardを気軽に使うTIPS | Zenn](https://zenn.dev/hnw/articles/36e70c0980c8786c7154)
#### [sshをproxy経由でつなぐ - @znz blog](https://blog.n-z.jp/blog/2018-08-12-ssh-over-proxy.html)
```bash
sudo apt-get install -y connect-proxy
......@@ -23,40 +27,47 @@ Host github github.com
```
#### sshのpublic key
`~/.ssh/config``IdentityFile`のファイル名+`.pub`のファイルの形式が不正の場合
```
key_load_public: invalid format
```
というメッセージが表示される
ファイル形式が、一見、正しくとも、`~/.ssh/authorized_keys`のように複数のpublic keyが登録されている場合(他のサーバの`authorized_keys`を流用している場合)に、
なぜか秘密鍵を利用したsshアクセスができなくなっている
ファイル形式が、一見、正しくとも、`~/.ssh/authorized_keys`のように複数のpublic keyが登録されている場合(他のサーバの`authorized_keys`を流用している場合)に、 なぜか秘密鍵を利用したsshアクセスができなくなっている
おそらく、サーバからではなく、localのpublic keyの先頭行と比較して弾いている?
### `~/.ssh/known_hosts`
defaultでhash化されているので、下記を`~/.ssh/config`へ適用するとhash化されなくなる
```
Host *
HashKnownHosts no
```
* [SSHのホスト鍵設定 \- 簡潔なQ]( https://qnighy.hatenablog.com/entry/2017/10/29/220000 )
* [github の IP アドレスをまとめて known\_hosts に登録する — KaoriYa]( https://www.kaoriya.net/blog/2016/07/04/ )
* [SSHのホスト鍵設定 - 簡潔なQ](https://qnighy.hatenablog.com/entry/2017/10/29/220000)
* [github の IP アドレスをまとめて known_hosts に登録する — KaoriYa](https://www.kaoriya.net/blog/2016/07/04/)
* hash化しないようにすれば,上記のページの通り,`github.com`のすべてのIPアドレスを一括で登録できるようになる
### sshd(/etc/ssh/sshd_config)
#### デフォルト値
`man sshd_config` [sshd\_config\(5\)]( https://www.freebsd.org/cgi/man.cgi?sshd_config(5) )
`man sshd_config` [sshd_config(5)](https://www.freebsd.org/cgi/man.cgi?sshd_config(5))
#### 設定ファイルの文法チェック
```bash
sshd -t
```
## rootユーザへパスワード入力無しでログイン(鍵不使用)
[linux \- How do I completely remove root password \- Stack Overflow]( https://stackoverflow.com/questions/11700690/how-do-i-completely-remove-root-password )
[linux - How do I completely remove root password - Stack Overflow](https://stackoverflow.com/questions/11700690/how-do-i-completely-remove-root-password)
1. rootのパスワードをなしにする
......@@ -77,63 +88,68 @@ PermitEmptyPasswords yes # default: no
UsePAM no # default: no
```
各デフォルト設定: [sshd\_config\(5\)]( https://www.freebsd.org/cgi/man.cgi?sshd_config(5) )
各デフォルト設定: [sshd_config(5)](https://www.freebsd.org/cgi/man.cgi?sshd_config(5))
`sudo service sshd restart`で再起動する
## ssh中にhang upした場合の対処法
* [SSH Escape Sequences \- Today I Learned]( https://til.hashrocket.com/posts/d909a57428-ssh-escape-sequences )
* [How can I break out of ssh when it locks? \- Ask Ubuntu]( https://askubuntu.com/questions/29942/how-can-i-break-out-of-ssh-when-it-locks )
* [networking \- Why do consoles sometimes hang forever when SSH connection breaks? \- Server Fault]( https://serverfault.com/questions/283129/why-do-consoles-sometimes-hang-forever-when-ssh-connection-breaks )
> There is a "secret" keyboard shortcut to force an exit :~) From the frozen session, hit these keys in order: Enter~. The tilde (only after a newline) is recognized as an escape sequence by the ssh client, and the period tells the client to terminate it's business without further ado.
* [SSH Escape Sequences - Today I Learned](https://til.hashrocket.com/posts/d909a57428-ssh-escape-sequences)
* [How can I break out of ssh when it locks? - Ask Ubuntu](https://askubuntu.com/questions/29942/how-can-i-break-out-of-ssh-when-it-locks)
* [networking - Why do consoles sometimes hang forever when SSH connection breaks? - Server Fault](https://serverfault.com/questions/283129/why-do-consoles-sometimes-hang-forever-when-ssh-connection-breaks)
例えば,2重でsshをしているときには,`<Enter>`, `~`, `~`, `.`を入力すればよい
(`~`の個数番目の`ssh`がcloseされる)
> There is a "secret" keyboard shortcut to force an exit :~~) From the frozen session, hit these keys in order: Enter~~. The tilde (only after a newline) is recognized as an escape sequence by the ssh client, and the period tells the client to terminate it's business without further ado.
例えば,2重でsshをしているときには,`<Enter>`, `~`, `~`, `.`を入力すればよい (`~`の個数番目の`ssh`がcloseされる)
### [Debian/shutdownやrebootするとssh接続の端末がハングする - Linuxと過ごす](https://linux.just4fun.biz/?Debian/shutdown%E3%82%84reboot%E3%81%99%E3%82%8B%E3%81%A8ssh%E6%8E%A5%E7%B6%9A%E3%81%AE%E7%AB%AF%E6%9C%AB%E3%81%8C%E3%83%8F%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B)
### [Debian/shutdownやrebootするとssh接続の端末がハングする \- Linuxと過ごす]( https://linux.just4fun.biz/?Debian/shutdown%E3%82%84reboot%E3%81%99%E3%82%8B%E3%81%A8ssh%E6%8E%A5%E7%B6%9A%E3%81%AE%E7%AB%AF%E6%9C%AB%E3%81%8C%E3%83%8F%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B )
サーバ側の設定でこの現象を防止することができるらしい
## ポートフォワーディング
[sshポートフォワーディング \- Qiita]( https://qiita.com/mechamogera/items/b1bb9130273deb9426f5 )
[sshポートフォワーディング - Qiita](https://qiita.com/mechamogera/items/b1bb9130273deb9426f5)
`-f`を指定するとbackgroundになり、わかりにくいので、単に、`-N`だけがおすすめ
フォワードする方向は片方向のみであることに注意
### リモートフォワード(リモートからローカルの方向へつなぐ)
`[local] -> [target] <-> [target2]` (矢印の方向にアクセス可能な環境を仮定)
`ssh -N $TARGET -R 8080:localhost:10080`
としたとき
`$TARGET:8080`->`localhost:10080`の方向つながるが、`$TARGET`外から`$TARGET:8080`へのアクセスはできない
`ssh -N $TARGET -R 8080:localhost:10080` としたとき `$TARGET:8080`-\>`localhost:10080`の方向つながるが、`$TARGET`外から`$TARGET:8080`へのアクセスはできない
`$TARGET`外からアクセスしたい場合は下記の3通り
* A. $TARGET上で`ssh -N $TARGET2 -R 9090:localhost:8080`としてコネクションを追加で貼る必要がある
* `$TARGET2:9090` -> `$TARGET:8080` -> `localhost:10080`となる
* `$TARGET2:9090` -\> `$TARGET:8080` -\> `localhost:10080`となる
* B. `/etc/ssh/sshd_config``GatewayPorts yes`を追加する(`GatewayPorts`のデフォルト値は`no`)
* C. 単に`$TARGET`を経由させずに直接`ssh -N $TARGET2 -R 9090:localhost:10080`
FROM_HOST -> HOST -> TO_HOSTの3wayのようなつなぎ方も可能
FROM_HOST -\> HOST -\> TO_HOSTの3wayのようなつなぎ方も可能
```bash
ssh -N $FROM_HOST -R $FROM_PORT:$TO_HOST:$TO_PORT
```
このとき、両方ともHOSTからsshできればOK(FROM_HOSTからTO_HOSTへssh接続するわけではない)
### ローカルフォワード(ローカルからリモートの方向へつなぐ)
ローカルフォワードのときは下記のオプションを付加すると簡単に指定できる
> -g Allows remote hosts to connect to local forwarded ports. If used on a multiplexed connection, then this option must be specified on the master process.
> \-g Allows remote hosts to connect to local forwarded ports. If used on a multiplexed connection, then this option must be specified on the master process.
`ssh -g -L 8080:$TARGET2:10080 $TARGET`
`localhost:8080` -> `$TARGET` -> `$TARGET2:10080`とつながる
`localhost:8080` -\> `$TARGET` -\> `$TARGET2:10080`とつながる
> * -f: Requests ssh to go to background just before command execution.
> * -N: Do not execute a remote command. This is useful for just forwarding ports.
> * \-f: Requests ssh to go to background just before command execution.
> * \-N: Do not execute a remote command. This is useful for just forwarding ports.
`-g`なし
```bash
$ ss -atn
LISTEN 0 128 ::1:8081 :::*
......@@ -141,6 +157,7 @@ LISTEN 0 128 127.0.0.1:8081 *:*
```
`-g`あり
```bash
$ ss -atn
LISTEN 0 128 *:8081 *:*
......@@ -148,6 +165,7 @@ LISTEN 0 128 :::8081 :::*
```
#### sshを利用しないローカルポートフォワーディング
`ssh -N -L 28080:127.0.0.1:8080 localhost`相当の処理
```bash
......@@ -158,6 +176,7 @@ socat TCP4-LISTEN:28080,reuseaddr,fork TCP4:127.0.0.1:8080
```
socatコマンドのバインド設定では外部からの通信も受け付けるようになっている
```bash
$ sudo lsof -i:28080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
......@@ -165,6 +184,7 @@ socat 75354 user 5u IPv4 0xc9257403876ca107 0t0 TCP *:28080 (LISTEN)
```
### 簡単にポートフォワーディングしてアクセスしたい
よく利用するリモートターゲットの`~/.ssh/config`の接続先に下記のようにまとめて記述しておくと`localhost:xxx`としてアクセスできるので便利(多重に接続してもエラーなし)
```
......@@ -194,9 +214,10 @@ ssh -N -R $PROXY_MACHINE 10080:localhost:80
ssh -N -g -L 8080:localhost:10080 localhost
```
`$PROXY_MACHINE:8080` => `$PROXY_MACHINE:10080` => `$FIREWALL_MACHINE:80`の方向でネットワークアクセスができる(これでwebsocketのport forwardingができることを確認済み)
`$PROXY_MACHINE:8080` =\> `$PROXY_MACHINE:10080` =\> `$FIREWALL_MACHINE:80`の方向でネットワークアクセスができる(これでwebsocketのport forwardingができることを確認済み)
### パフォーマンス測定
* `mkfifo`: 500-540MiB/s
* `nc`: 300MiB/s
* `nc`,`socat`: 280MiB/s
......@@ -204,6 +225,7 @@ ssh -N -g -L 8080:localhost:10080 localhost
* `nc`,`ssh -C`: 40MiB/s
`mkfifo`: 500-540MiB/s
```bash
mkfifo ncpipe
pv < ncpipe > /dev/null
......@@ -211,6 +233,7 @@ pv < /dev/random > ncpipe
```
`nc`: 300MiB/s
```bash
# receiver
nc -l 8080 | pv > /dev/null
......@@ -233,7 +256,8 @@ pv < /dev/random | nc localhost 28080
```
## `~/.ssh/config`なしの多段ProxyCommand利用時の注意
[ssh\_config\(5\) \- Linux manual page]( https://man7.org/linux/man-pages/man5/ssh_config.5.html#TOKENS )
[ssh_config(5) - Linux manual page](https://man7.org/linux/man-pages/man5/ssh_config.5.html#TOKENS)
`%h`/`%p`などは多段化するときにはエスケープする必要がある(e.g. `%h:%p`, `%%h:%%p`, `%%%%h:%%%%p`)
......@@ -243,27 +267,30 @@ ssh -oProxyCommand='ssh -W %h:%p -oProxyCommand="ssh -W %%h:%%p -oProxyCommand=\
正しいケース
HOST_A -%%h:%%p-> HOST_B -%h:%p-> HOST_C
の順番で接続する
HOST_A -%%h:%%p-\> HOST_B -%h:%p-\> HOST_C の順番で接続する
```bash
ssh -oProxyCommand='ssh -W %h:%p -oProxyCommand="ssh -W %%h:%%p HOST_A" HOST_B' HOST_C hostname
```
誤ったケース
HOST_A -%h:%p-> HOST_Bで意図せずに接続されてしまうので、
HOST_A -%h:%p-\> HOST_Bで意図せずに接続されてしまうので、
HOST_A -%h:%p-\> HOST_Cとなる
HOST_A -%h:%p-> HOST_Cとなる
```bash
ssh -oProxyCommand='ssh -W %h:%p -oProxyCommand="ssh -W %h:%p HOST_A" HOST_B' HOST_C hostname
```
## ダイナミックポートフォワード
ssh接続先をsocks proxyサーバとして利用する機能で,firefoxのプロキシ設定をsocksとすることで利用できる(curlならば`--socks5`オプションを利用する)
[ssh DynamicForwardでセキュアなssh接続 \- 自分用メモ]( https://hoshi-sbg.hatenablog.com/entry/2020/03/18/180234 )
[ssh DynamicForwardでセキュアなssh接続 - 自分用メモ](https://hoshi-sbg.hatenablog.com/entry/2020/03/18/180234)
## Xをサポートしていない環境でクリップボードのコピーを行う
[Forward your clipboard via SSH reverse tunnels](https://gist.github.com/dergachev/8259104)
下記を`~/.ssh/config`に加える(単なる`Host *`では、例えば、git接続時にも適用されてしまうことに注意)
......@@ -274,6 +301,7 @@ Host hoge*
```
下記のクリップボードサーバを動かす
```bash
while true; do nc -l 5556 | xclip -sel clip; done
......@@ -284,6 +312,7 @@ fi
```
ssh先のサーバにて
```bash
function c() {
# way 1
......@@ -329,6 +358,7 @@ EOF
```
## ssh先でterminal経由でファイルをコピー&ペーストしたい
* clipboardを利用する方法
* e.g. base64
* 長すぎると,terminalの挙動がとてつもなく重くなる(zshのpluginの影響であり,bashなら問題ない)
......@@ -340,14 +370,15 @@ EOF
dotfilesに`pack`コマンドを作成した
## ssh rsa非推奨
[SSH 公開鍵を ssh-rsa から強い暗号に書き換える - Qiita](https://qiita.com/katzueno/items/4319fffc8b0b0b50d8a6)
e.g. `ssh-keygen -t ecdsa -b 521`
## 💡圧縮
## :bulb:圧縮
* [ssh(1) manページ](https://nxmnpg.lemoda.net/ja/1/ssh)
* [ssh_config(5) manページ](https://nxmnpg.lemoda.net/ja/5/ssh_config)
* デフォルトで圧縮はOFFである
* `ssh -C``ssh -o Compression=y`のどちらかを指定すればよい(`gzip`とおなじ`6`(速い/低圧縮率 `1` - `9` 遅い/高圧縮率)であり、プロトコルバージョン`1`のみ変更可能であるので、事実上変更不可である)
* e.g. 100MB/s程度のリモートフォワーディングの場合はおおよそ`sshd`のCPU利用率が50%ほどであった
......@@ -355,6 +386,7 @@ e.g. `ssh-keygen -t ecdsa -b 521`
* パフォーマンス測定の結果、通常のsshのフォワーディングが260MiB/sのところ、40MiB/sとなった(この場合、sshによる実際の圧縮率は不明)
圧縮している場合のバッファリングの挙動が不明であるが、次の実験をする限りはバッファリングによる待機時間は非常に短いのではないかと考えられる
```bash
# ローカルポートフォワーディング
ssh -C -N -L 28080:127.0.0.1:8080 localhost
......@@ -367,22 +399,35 @@ nc -l 8080
```
## tips
### [while内でsshを使うと1回で止まる \- Miuran Business Systems]( http://site.m-bsys.com/error/whileread-ssh )
### [while内でsshを使うと1回で止まる - Miuran Business Systems](http://site.m-bsys.com/error/whileread-ssh)
use `ssh -n` for avoid staling `stdin` (`-n Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background.`)
### [sshの鍵を作るときにちょっとだけ気にしたいこと \| Developers\.IO]( https://dev.classmethod.jp/articles/ssh-keygen-tips/ )
### [sshの鍵を作るときにちょっとだけ気にしたいこと | Developers.IO](https://dev.classmethod.jp/articles/ssh-keygen-tips/)
`-C ""`を追記することで,hostnameが共通鍵にコメントとしてはいることを防止できる
### ssh上でreboot
rebootの処理自体はsshが親プロセスでどうさするのではないため、セッションが切れても問題ないと考えられる
### **ControlMaster機能を利用すると既に接続済みのセッションを再利用できるので接続が高速化する**
[SSH接続を10倍速くするたった3行の設定 #SSH - Qiita](https://qiita.com/suin/items/1708dc78fc412297f885)
実際に試したところ体感的には変化なし
## トラブルシューティング
### 意図していない秘密鍵が利用される
`IdentitiesOnly` `yes`: IdentityFile で指定した秘密鍵でのみ認証を試みる設定を`~/.ssh/config`へ追加すると良い
デフォルト状態(`no`)に設定しておくと`ssh-add`で登録した秘密鍵も利用して認証を試みるので、基本的には`yes`にしておくほうが意図しない挙動とならない
### ssh接続時に`Load key "/home/user/.ssh/hoge_id_rsa": error in libcrypto`というエラー
```bash
Load key "/home/user/.ssh/hoge_id_rsa": error in libcrypto
user@address: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
......@@ -396,9 +441,11 @@ bad_id_rsa: ASCII text
$ file good_id_rsa
good_id_rsa: PEM RSA private key
```
なお、`bat`コマンドでも色がつくので違いがわかる
秘密鍵の正しい形式
```
-----BEGIN RSA PRIVATE KEY-----
......
......@@ -406,19 +453,23 @@ good_id_rsa: PEM RSA private key
```
### VSCodeのsshではgit情報を裏で処理しているための負荷が発生する
[Visual Studio CodeでのSSH接続により、EC2サーバーが高負荷になり動かなくなった - エキサイト TechBlog.](https://tech.excite.co.jp/entry/2022/09/27/153341)
### sshの接続が遅い
認証鍵を利用する際にDNSアクセスがあるため、DNSの指定がおかしいと遅くなるケースがある
[ubuntu - SSH by key incredibly slow - Server Fault]( https://serverfault.com/questions/692449/ssh-by-key-incredibly-slow )
認証鍵を利用する際にDNSアクセスがあるため、DNSの指定がおかしいと遅くなるケースがある [ubuntu - SSH by key incredibly slow - Server Fault](https://serverfault.com/questions/692449/ssh-by-key-incredibly-slow)
#### 鍵を使わずにssh ログインしたいときのsshオプション
```bash
ssh -o PubkeyAuthentication=no $IP_ADDR
```
## ssh-agent
### ssh-agentの設定
`eval $(ssh-agent)`の中身(macの場合)
```bash
......@@ -451,32 +502,38 @@ ssh-add -d <(ssh-add -L | cut -d" " -f1,2 | awk 'NR==XXX')
```
削除する際に下記のようなエラーがでても、実際には、そのファイルが存在しても、formatが正しくない時にも下記のメッセージが表示される
```
Bad key file XXX_id_rsa: No such file or directory
```
### 指定したキーが無視されているような挙動となっている
`ssh-add`の結果は`~/.ssh/config``ssh -i`よりも優先されるため、注意
### ⭐ssh接続先でgit cloneしたい
### :star:ssh接続先でgit cloneしたい
1. ホストマシンでssh-agentに秘密鍵を追加する
下記のコマンドはシェルごとに実行する必要がある
```bash
eval $(ssh-agent)
ssh-add ~/.ssh/github_id_rsa
ssh-add -L
```
なお、すでにssh接続していた先のサーバにも上記の変更はリアルタイムに反映される(ホストマシンの`ssh-agent`の情報を利用しているためであると推測される)
2. `ssh`コマンドに`-A`オプションをつける or `~/.ssh/config``ForwardAgent yes`を追加する
3. リモートでsshログインして、`ssh-add -L`して確かめてから、`git clone git@github.com:ORG/REPO.git`をする
#### ssh-agentの機能で適切にfetchできなかった原因
まず、`ssh -T git@github.com`で確認する
該当するgitのリモートのアドレスが原因である可能性がある
```bash
$ git remote -v
origin github.com:ORG/REPO.git (fetch)
......
......