SambaのSMBプロトコルのサポート状況

最近会社で聞かれて答えたことをまとめてみました。

SambaのSMBプロトコルのサポート状況です。

事の発端は、Windows10におけるSMB1.0/CIFS自動削除機能です。Samba-3.xで構築したファイルサーバーを使用している場合、長期間に渡ってそのファイルサーバーにアクセスしていないWindows10端末からアクセスができなくなる場合がある、まさにその場面に遭遇してしまったというわけです。

Windows側の詳細条件は、[公式情報](https://support.microsoft.com/ja-jp/help/4034314/smbv1-is-not-installed-by-default-in-windows)にあります。例えば、クリーンインストールの場合に、端末稼働時間中の、SMBv1クライアントの未使用累積時間が15日に達すると自動削除機能が発動するといったことが書いてあります。その他の情報は"Windows10 SMB1.0 自動削除"などで検索すれば出てきます。画面設定は以下の場所です。

![Windowsの機能 - SMB1.0関連.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381550/aa5c5764-e30f-230d-81a3-ecdd790c3164.png)

じゃあSamba側の詳細条件はどうでしょうか。つまりSambaのSMBプロトコルバージョンのサポート状況やデフォルト設定はどうなっているのでしょうか。

セキュリティ的にはSMB1.0を使わないほうがいいです。SMB1.0を使わないためにはSambaをどのバージョンまで上げる必要があるのでしょうか。

# SambaのWebドキュメントを見る

[SambaのWebベースのドキュメント](https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html)を見ると、最新バージョンではSMB3(SMB3_11)に対応していることが分かります。しかし、RPMインストールしている場合などを考えると、どのバージョンからSMB3に対応し始めたかを知りたいでしょう。

リリース履歴に載っているかもしれません。でも今回は、バージョン別のsmb.confのドキュメントから情報を入手してみることにします。

## 結論

### サポートバージョン

表の説明は表の下に書きます。まずはまとめた情報から。

| Samba | CORE(PLUS) | LANMAN1/2, NT1 | SMB2 | SMB2_02 | SMB2_10 | SMB2_22 | SMB2_24 | SMB3_00 | SMB3_02 | SMB3_10 | SMB3_11 |
|:------|:-----------|:----|:----|:---------|:--------|:--------|:--------|:--------|:--------|:--------|:--------|
| 3.2 | O | O | - | - | - | - | - | - | - | - | - |
| 3.3 | O | O | - | - | - | - | - | - | - | - | - |
| 3.4 | O | O | - | - | - | - | - | - | - | - | - |
| 3.5 | O | O | E | - | - | - | - | - | - | - | - |
| 3.6 | O | O | O | - | - | - | - | - | - | - | - |
| 4.0 | C | O | - | O | O | O | O | O | - | - | - |
| 4.1 | C | O | - | O | O | O | O | O | - | - | - |
| 4.2 | C | O | - | O | O | O | O | O | O | - | - |
| 4.3 | C | O | - | O | O | O | O | O | O | O | O |
| 4.4 | C | O | - | O | O | O | O | O | O | O | O |
| 4.5 | C | O | - | O | O | O | O | O | O | O | O |
| 4.6 | C | O | - | O | O | O | O | O | O | O | O |
| 4.7 | C | O | - | O | O | O | O | O | O | O | O |
| 4.8 | C | O | - | O | O | O | O | O | O | O | O |
| 4.9 | C | O | - | O | O | O | O | O | O | O | O |
| 4.10 | C | O | - | O | O | O | O | O | O | O | O |

この表は"smb.conf"の"max protocol","server max protocol","client max protocol"に指定可能なプロトコルを"サポートされている"と見なして、バージョン別のプロトコルサポート状況をまとめたものです。Samba-3.xでは"max protocol"、Samba-4.xでは"server max protocol"と"client max protocol"が指定可能です。

プロトコルバージョンの表記は、smb.confの表記に合わせてあります。

表の"O"がサポートされていること、表の"-"がサポートされていないことを表します。表の"E"はサポートされているが試験的(experimental)であることを表しています。

表の"C"は"client max protocol"に指定可能、"server max protocol"には指定不可ということを表します。

列タイトルが"SMB2"となっているものは、Samba-3.xだけを記載しました。"SMB2"という指定は、そのSambaが対応しているSMB2ダイアレクト(方言)すべてを表します。Samba-4.xはどのSMB2ダイアレクトに対応しているかが、smb.conf.5.htmlに記載されています。しかし、Samba-3.xには記載されていません。"SMB2"でひとまとめにされています。そのため、Samba-4.xは細分化して表に記載、Samba-3.xは一括りにした"SMB2"にまとめて表に記載したわけです。

上表を見ると、以下のことが言えます。
* Samba-3.4以下は、SMB2以上に対応していない
* Samba-3.5と3.6は、SMB2に対応している
 * ただし、Samba-3.5は試験的対応なので、実質はSamba-3.6から対応したと考えるのがよいだろう
* SMB3に対応しているのはSamba-4.x以上

### デフォルトプロトコル

表の説明は表の下に書きます。まずはまとめた情報から。

| Samba | max protocol | server max protocol | client max protocol | min protocol | server min protocol | client min protocol |
|:------|:-------------|:--------------------|:--------------------|:-------------|:---------------------|:--------------------|
| 3.2 | NT1 | - | - | CORE | - | - |
| 3.3 | NT1 | - | - | CORE | - | - |
| 3.4 | NT1 | - | - | CORE | - | - |
| 3.5 | NT1 | - | - | CORE | - | - |
| 3.6 | NT1 | - | - | CORE | - | - |
| 4.0 | - | SMB3 → SMB3_00 | SMB3 → SMB3_00 | - | LANMAN1 | CORE |
| 4.1 | - | SMB3 → SMB3_00 | SMB3 → SMB3_00 | - | LANMAN1 | CORE |
| 4.2 | - | SMB3 → SMB3_02 | default → NT1 | - | LANMAN1 | CORE |
| 4.3 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.4 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.5 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.6 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.7 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.8 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.9 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |
| 4.10 | - | SMB3 → SMB3_11 | default → NT1 | - | LANMAN1 | CORE |

Samba-4.xの"server max protocol"や"client max protocol"のデフォルト指定は"default"あるいは"SMB3"です。上表には、その設定値が意味する実効値を"→"の右に記載してあります。

上表を見ると、以下のことが言えます。
* Samba-3.xは、SMB2に対応したバージョンも含めてNT1が"max protocol"のデフォルトとなっている
* Samba-4.xは、その時点で対応している最高バージョンが"server max protocol"のデフォルトとなっている

## 情報をまとめるために使用した道具

### 環境

今回はDockerでCentOS 6を使用しました。つまり以下のコマンドで起動した環境を使用しました。

```
docker start -it centos:6
```

作業用ディレクトリを作成して、そのディレクトリで作業しました。

```
mkdir -p /tmp/samba
cd /tmp/samba
```

このディレクトリにシェルスクリプトを3種作成しました。それらを順次動かすことで、取りまとめられた情報が標準出力に表示されます。

上記の背景のため、使用コマンドはCentOS 6にデフォルトインストールされているものに限りました。

以下、シェルスクリプトがいくつか登場します。スクリプトに色々と粗がある点は無視してください。

### バージョン別のドキュメントの取得

まずは、バージョン別のドキュメント情報を取得してみます。これには以下のシェルスクリプトを使用しました。

```
#!      /bin/bash

echo https://www.samba.org/samba/docs/man/ \
| xargs -r -n 1 curl -s \
| awk '/<p>/,/<\/p>/' \
| awk 'BEGIN {RS="\""} {print}' \
| grep -F '..' \
| sed 's_^../_https://www.samba.org/samba/docs/_' \
| sed 's_$_smb.conf.5.html_' \
| awk -F/ '{print $6 ".html", $0}' \
| while read -r filename url; do
        curl -s --output ${filename} ${url}
done
```

これを実行すると、バージョン別のsmb.conf.5.htmlがダウンロードされます。3.2～3.6、4.0～4.10、currentの17ファイルを取得することになります。

### "max protocol"関連キーワード情報の取得

取得したHTMLファイルから、以下のキーワードに関する説明部分だけを切り出して別々のファイルに書き出してみます。
* max protocol (Samba-3.x)
* min protocol (Samba-3.x)
* server max protocol (Samba-4.x)
* server min protocol (Samba-4.x)
* client max protocol (Samba-4.x)
* client min protocol (Samba-4.x)

これには以下のシェルスクリプトを使用しました。

```
#!      /bin/bash

ls *.html \
| while read -r filename; do
        basename=${filename%.*}

        cat ${filename} \
        | awk '/^max protocol/,/^$/' \
        | sed 's_</*p>_\n_g' \
        | sed 's_<[^\>]*>__g' \
        > ${basename}-max.txt

        cat ${filename} \
        | awk '/^min protocol/,/^$/' \
        | sed 's_</*p>_\n_g' \
        | sed 's_<[^\>]*>__g' \
        > ${basename}-min.txt

        cat ${filename} \
        | awk '/^server max protocol/,/^$/' \
        | sed 's_</*p>_\n_g' \
        | sed 's_<[^\>]*>__g' \
        > ${basename}-server-max.txt

        cat ${filename} \
        | awk '/^server min protocol/,/^$/' \
        | sed 's_</*p>_\n_g' \
        | sed 's_<[^\>]*>__g' \
        > ${basename}-server-min.txt

        cat ${filename} \
        | awk '/^client max protocol/,/^$/' \
        | sed 's_</*p>_\n_g' \
        | sed 's_<[^\>]*>__g' \
        > ${basename}-client-max.txt

        cat ${filename} \
        | awk '/^client min protocol/,/^$/' \
        | sed 's_</*p>_\n_g' \
        | sed 's_<[^\>]*>__g' \
        > ${basename}-client-min.txt

done
```

### 必要な要素の抽出

取得したTXTファイルから、欲しい情報だけを抜き出します。これには以下のシェルスクリプトを使用しました。

```
#!      /bin/bash

ls *.txt \
| while read -r filename; do
        if [ ! -s ${filename} ]; then
                continue
        fi

        basename=${filename%.*}
        version=${basename%%-*}

        echo Filename: ${filename}
        echo Version: ${version}

        cat ${filename} \
        | head -n 1 \
        | xargs -r echo Keyword:

        cat ${filename} \
        | tr '\.' '\n' \
        | grep -E '^[A-Z0-9]{2}' \
        | grep -v '^IPC' \
        | sed 's_:.*$__' \
        | tr '\n' ',' \
        | sed 's/,$//' \
        | xargs -r echo Supported: \

        cat ${filename} \
        | tr -d '\n' \
        | sed -e 's_.*Default:__' -e 's_Example.*__' -e 's_.* __g' \
        | xargs -r echo Default: \

        echo

done
```

### 出力結果抜粋

出力結果の上部を抜粋して記載しておきます。

```
Filename: 3.2-max.txt
Version: 3.2
Keyword: max protocol (G)
Supported: CORE,COREPLUS,LANMAN1,LANMAN2,NT1
Default: NT1

Filename: 3.2-min.txt
Version: 3.2
Keyword: min protocol (G)
Default: CORE

Filename: 3.3-max.txt
Version: 3.3
Keyword: max protocol (G)
Supported: CORE,COREPLUS,LANMAN1,LANMAN2,NT1
Default: NT1

Filename: 3.3-min.txt
Version: 3.3
Keyword: min protocol (G)
Default: CORE

      : (略)

Filename: 3.6-max.txt
Version: 3.6
Keyword: max protocol (G)
Supported: CORE,COREPLUS,LANMAN1,LANMAN2,NT1,SMB2
Default: NT1

      : (略)

Filename: 4.10-server-max.txt
Version: 4.10
Keyword: server max protocol (G)
Supported: LANMAN1,LANMAN2,NT1,SMB2,SMB2_02,SMB2_10,SMB2_22,SMB2_24,SMB3,SMB3_00,SMB3_02,SMB3_10,SMB3_11
Default: SMB3

      : (略)
```

# 最後に

かなり手を抜きました。スクリプトの粗を挙げます。

* プログラム(スクリプト)とデータ(ダウンロードされたファイルと加工途中のファイル)が同一フォルダに含まれている
 * 一発ものということで手を抜きました
* ちゃんとHTMLパースしていない
 * 一発ものということで手を抜きました
* sedの後方参照を使えばもっと簡単になるのでは
 * 得意ではないので、即席で自分のために作る場合は複数のsedを組み合わせることで代用しています
* 2つ目のシェルスクリプトにfunctionを使っていない
 * 一発ものということで手を抜きました
* Supportedが見にくい、そこからQiitaの表を起こすのは大変ではないか
 * これ以上うまい表現、加工方法を思いつきませんでした
* 最終結果が行列志向の出力結果になっていない
 * これ以上うまい表現、加工方法を思いつきませんでした

などといったように粗は色々あります。