SSH Tips


## はじめに
  
今回は、そこそこセキュアなSSH Serverを作成する方法とか、接続する方法などを紹介していきたいと思います。

なお、はじめに私の個人的な考えを少しだけ述べておくことにします。

はじめに、「そこそこセキュアなSSH Serverを作るのには、時間もかからないし、特別な知識も全く必要ない」ということです。

なぜかという理由は山ほど考えられますが、通常、ルーターやコンピュータというものは、外部からは接続できないようになっているからです。これは、ルータの設定やOSの設定によるものです。

だから、公式的な方法や設定では、いくらセキュアなものを考えても、あまり意味は無いと考えています。さすがにこれはダメだろって言うこと以外避けるようにすれば、それで十分セキュリティ的な要件を満たしていることも多いと思います。

例えば、WANから公式的な方法でLAN内のSSH Serverに接続しようとする場合、通常は、かなりの面倒な手順を踏まなければ接続できません。具体的には、WAN側で使うGlobal IP Address(グローバルIPアドレス)へのアクセスを特定のLAN内Local IP Address(ローカルIPアドレス)に転送しなければなりません。そういった処理が必要になります。また、アドレスを転送するだけでは通常はダメで、それはルーターにファイアウォールが設定されている場合がほとんどだからです。

したがって、ルーターへの特定ポートへの接続を許可する必要があります。イメージで言うと、WANとLANの間にある壁に穴を開けるというイメージですね。

しかし、そのままでは、一旦穴に入られると、LAN内イメージの見通しが良いため、セキュリティ的にはマイナスである事が少なくありません。したがって、ルーターに開けた穴は、特定のLAN内コンピュータの穴に繋げておくと良いと考えられます。もちろん、この場合は、そのコンピュータのセキュリティなども考慮しなくてはいけなくなりますが、LANない全部のコンピュータを監視するよりはマシだと思いますので、個人的には、開けたポートは、必ず特定のPCに繋げておくということが基本的にはおすすめだと考えています。

更に、SSH Serverの設定を(1)鍵方式にし、(2)Passwordでの接続を禁止して、(3)rootのアクセスを禁止しておけば、セキュリティ的には、いうことはほとんどありません、と思います。例えば、(3)のrootアクセス禁止に関してですが、たとえ侵入されたとしてもrootのパスワードがなければ、ほとんど何もできないでしょう。つまり、(1),(2)が侵入を防ぐための設定。(3)が仮に侵入された時の設定です。

これを公式的な方法で接続するのは、かなり面倒です。もちろん、鍵長にもよりますが、通常はこんな面倒な方法で侵入を試みようとする人は少ないのではないでしょうか。

では、どういった方法が一番手っ取り早い接続を実現できるのかというと、例えば、バックドアを設置するのが一番手っ取り早い接続を実現できます。

バックドアというのは、いわばサーバーから情報を発信させることで、接続を簡単にします。通常、SSHサーバーというのは接続を待ち、それ自体がクライアントに情報を発信するということはありません。しかし、バックドアは違います。バックドアを仕掛けられたサーバーは自ら情報を発信する発信源にもなります。だからこそ、ルーターやファイアウォールなどの仕組みを飛ばして接続できるというわけです。少し簡単すぎる説明ですが、こんな感じでイメージしてもらうとわかりやすいと思います。

ここで、何が言いたいのかというと、公式的な方法で侵入されるということは少ないので、設定は当たり前のことを当たり前のようにやっておくこと、それで十分だと思うということです。もちろん、それぞれの環境に合わせた設定というのが必要ではありますが、今回は、より一般的な話をしますので、そんな感じです。

## 最初の接続

最初の接続は、Passwordでアクセスするのが一番手っ取り早いと思います。ルーターやファイアウォールの設定がなされているのなら、基本的にはデフォルトでも十分に機能している場合が多いと思いますが、そうであるなら、Passwordのrootアクセスでも問題無いと思います。一応、SSH Serverは、Arch Linuxを対象に構築しますが、OSによって異なる部分もあるので読み替えてください。

```bash:サーバー
## root権限で設定する
$ su -

## ssh server,ssh clientのインストール
# pacman -S openssh

## ssh serverの起動と自動起動の設定
# systemctl start sshd
# systemctl enable sshd

## 使用してるlan deviceのlocal ip addressを確認
# pacman -S net-tools
# ifconfig
> 192.168.1.3
```

```bash:クライアント
# 接続確認と終了
$ ssh root@192.168.1.3
# exit

# 鍵コピーのためのスクリプトをインストール(必要ないかもしれない)
$ sudo pacman -S ssh-copy-id

# 公開鍵の作成と登録(登録先がrootではなくuserであることに注意)
$ ssh-keygen -t rsa
$ ssh-copy-id -i ~/.ssh/id_rsa.pub user@192.168.1.3

# SSHの最低限の設定
$ ssh root@192.168.1.3
```

```bash:サーバー
## ssh 接続して設定を変更している
$ vi /etc/ssh/sshd_config
## 以下を追記します
Port 11023
PasswordAuthentication no
PermitRootLogin no

## ssh serverの再起動
# systemctl restart sshd
```

```bash:クライアント
$ ssh user@192.168.1.3 -i ~/.ssh/id_rsa -p 11023
```

## クライアントの設定ファイル

ここで、わざわざ接続するたびに長いコマンドを入力するのは面倒です。したがって、通常は、設定ファイルに書きます。ちなみに、`username`は、サーバーの`/home/`にあるディレクトリ名を入れればよいです。`/home/hoge`なら`User hoge`です。

```bash:
Host arch-ssh-server-01
    User username
    HostName 192.168.1.3
    Port 11023
    IdentityFile ~/.ssh/id_rsa
```

これによって、`$ ssh arch-ssh-server-01`でアクセスできます。

## WAN側からのSSH接続


```bash:
$ ssh user@111.222.333.444 -i ~/.ssh/id_rsa -p 11023
```

ただし、あくまでWANからのアクセスを特定のLAN内ポートに転送する設定なので、LANからのアクセスは転送しません。したがって、グローバルIPアドレスを外部サーバー経由で変化させて接続するか、もしくは他のスマホ回線を使うなどして実験してください。

グローバルIPアドレスは、通常、ルーターのものがWANへのアクセスに使われます。つまり、ルーターに割り当てられた一つのグローバルIPアドレスを使って、LAN内のコンピュータはWANにアクセスしているわけですね。グローバルIPは以下のコマンドなどでWebサービスから確認するのも良いし、ルーターから確認するのでも良いと思います。

```bash:
$ curl inet-ip.info
```

ルーターのアドレスは、コンピュータのLANアドレスから判断して、ブラウザから設定できるようになっていると思います。Local IPが`192.168.22.3`だった場合、ルーターのLANアドレス(Local IP Addressのこと)は`192.168.22.1`です。つまり、3番目と4番目の数字が重要です。4番目は通常1です。3番目はルーターの設定によります。


また、WAN側からのSSH接続には、Global IP Addressが必要になりますが、DDNS(ダイナミックドメインネームサーバー)を使用しても良いです。

独自に管理したいのなら、ルーターのグローバルIPをGitサーバーなどで管理する方法もあります。サーバーのグローバルIPが変更されれば、リポジトリにコミットするわけですね。

Gitホストサービスのプライベートリポジトリを使ってもいいですが、[gitolite](https://wiki.archlinux.org/index.php/Gitolite)などを使って、自分でGitリポジトリを管理するサーバーを作ってもいいと思います。

### ssh-keygen

公開鍵、秘密鍵の作成コマンドです。公開鍵は`.pub`が付きます。そして、サーバーに登録するのは公開鍵です。鍵の作成は通常、クライアント側が行います。

ssh-keygenは、何も指定しないと、`RSA`鍵の`2048 bit`が使用されます。鍵作成と登録は通常クライアントから行います。分かりにくいので注意してください。ssh-copy-idは、単に公開鍵をサーバーに登録するためのスクリプトです。`scp`でも同じことができます。

ここでは、強力な`ECDSA`鍵を使うことにします。

```bash:
$ ssh-keygen -N "" -t ecdsa -b 521 -f ~/.ssh/id_ecdsa_hoge

$ ssh-copy-id -i ~/.ssh/id_ecdsa_hoge.pub user@192.168.1.3
```

| オプション | 内容|
| ---|---|
| -N ""|パスを省略する|
| -t ecdsa| ECDSA鍵を使用する|
| -b 521 | RSAの15360 bitに相当する鍵長を指定する|
| -f hoge| 公開鍵、秘密鍵の保存場所とファイル名を指定する| 

公開鍵は、サーバーに公開されている鍵のことであり、場合によっては、WAN上で公開されることもあります。つまり、この公開鍵の暗号を解読されると、アクセス可能となります。

したがって、できるだけ鍵長は長いものがお勧めですし、更に言えば、デフォルトや最も多く使われている鍵というものは使用すべきではないと考えています。

なぜなら、OSの攻撃率やコンピュータ・ウィルスを見る限りでは、最も狙われやすいのは、ユーザーが最も多い場所に限られるからです。なので、セキュリティを考慮するならば、よく使われる設定やツールは基本的には避けるのが無難な場面というのも少なからずあると私は考えています。

### iptables

[iptables]()は、ファイアウォールに相当するツールです。パケットが通るまでの図式は以下になります。これを使用すると、

```bash:
       XXXXXXXXXXXXXXXXXX
                             XXX     Network    XXX
                               XXXXXXXXXXXXXXXXXX
                                       +
                                       |
                                       v
 +-------------+              +------------------+
 |table: filter| <---+        | table: nat       |
 |chain: INPUT |     |        | chain: PREROUTING|
 +-----+-------+     |        +--------+---------+
       |             |                 |
       v             |                 v
 [local process]     |           ****************          +--------------+
       |             +---------+ Routing decision +------> |table: filter |
       v                         ****************          |chain: FORWARD|
****************                                           +------+-------+
Routing decision                                                  |
****************                                                  |
       |                                                          |
       v                        ****************                  |
+-------------+       +------>  Routing decision  <---------------+
|table: nat   |       |         ****************
|chain: OUTPUT|       |               +
+-----+-------+       |               |
      |               |               v
      v               |      +-------------------+
+--------------+      |      | table: nat        |
|table: filter | +----+      | chain: POSTROUTING|
|chain: OUTPUT |             +--------+----------+
+--------------+                      |
                                      v
                               XXXXXXXXXXXXXXXXXX
                             XXX    Network     XXX
                               XXXXXXXXXXXXXXXXXX
```

Archでは、`iptables.rules`がないので、作成します。設定ファイルがある場合はそれを編集します。



```
# cp /etc/iptables/empty.rules /etc/iptables/iptables.rules
# cat /etc/iptables/iptables.rules

# systemctl start iptables
# systemctl enable iptables
```


### 踏み台を利用して接続する

```bash:~/.ssh/config
Host server1
	HostName 111.222.333.444
    Port 11023

Host server2
	HostName 192.168.1.3
	Port 11023
	ProxyCommand ssh -W %h:%p server
```

これで、`$ ssh server2`で接続できます。重要なのは、`ProxyCommand`で`nc`を使うか、`-W`を使っても良いです。

### SSH 接続を高速にする

```bash:~/.ssh/config
Host examplehost.com
  ControlMaster auto
  ControlPersist yes
  ControlPath ~/.ssh/socket-%r@%h:%p
```

```bash:サーバー
# echo 'Compression yes' >> /etc/ssh/sshd_config
```

### X を飛ばす

Xを飛ばすと、VNCサーバーのようなことができます。

```bash:
$ ssh -X user@host
```

詳しくは、Arch Wikiを見てください。あと、便利な設定や間違いなど気づいたことがあれば、コメントのほうよろしくです。

https://archlinuxjp.kusakata.com/wiki/Secure_Shell

  
##その他

###ローカル内のIPアドレスをスキャンする

```bash:
$ sudo pacman -S arp-scan

$ sudo arp-scan -l
```

###意思疎通を図る、サーバーが落ちていないか、ネットワークにつながっているか調べる

```bash:
$ ping 192.168.1.3
```

###コンピュータのローカルIPを固定する

通常、必要なツールがインストールされていると、ローカルIPはルーターによって自動で割り当てられます。しかし、OSの設定によってそれを固定することができます。

例えば、Arch Linuxでは以下の様な固定方法があります。Windowsの場合は、ネットワーク設定よりLANデバイス項目を触ってれば分かりそうなので、割愛します。

```bash:
$ sudo cp /etc/netctl/examples/ethernet-static /etc/netctl/eth0

$ sudo vim /etc/netctl/eth0
Interface=eth0
Connection=ethernet
IP=static
Address=('192.168.1.24/25')
#Routes=('192.168.0.0/24 via 192.168.1.2')
Gateway=('192.168.1.1')
DNS=('192.168.1.1')

$ sudo netctl enable eth0
$ sudo netctl start eth0
```
重要なのは、`Address=('192.168.1.24/25')`です。これは、`192.168.1.24`で固定する設定です。