プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

QNAP NAS の admin 無効後のスナップショットレプリカでトラブル

知り合いの方と Twitter でやり取りしてたら、今更ながら QNAP でマルウェア被害が起こってることに気がつきました。

QlockerランサムウェアについてのQNAPからのお知らせ

怖い怖い。

幸い、自分の NAS はこれには巻き込まれてなかったんですが、この機にセキュリティをちょっとだけ強化したいと思い立ちました。

NASのコントロールパネルにログインするたびに、

  • デフォルトの admin ユーザーを使ってるので無効にして、新しい管理者アカウント使いましょう
  • 2段階認証を有効にしましょう

との警告が出てくるので、これに対応することにしました。

で、これに対応したら、スナップショットレプリカで問題が起きたので、そのあたりに事をメモしておきます。

なお、 試した際の QTS のバージョンなどは下記の通りです。

  • スナップショットレプリカの送信側: QNAP TS-231P, QTS 5.0.0.1808
  • スナップショットレプリカの受信側: QNAP TS-251+, QTS 4.5.4.1800

なお、参考までに、セキュリティ強化のアドバイスがQNAPのブログにありますので、リンク張っときます。

QNAP NASを無防備にインターネットに直接接続してはいけない理由とは | QNAP ブログ

admin の無効化

やりかたは簡単で、公式のドキュメントに従えばすぐに終わります。

  1. 新規に管理者権限を持つユーザーを作成
  2. 新しく作った管理者ユーザーでログイン(以後、新規追加管理者、と呼ぶことにします)
  3. デフォルトの admin を無効にする

とすればできます。 そのうえで、『コントロールパネル』->『アプリケーション』->『Telnet/SSH』で、『アクセス許可の編集』を選択し、

f:id:junichim:20210921113515p:plain

新規追加管理者に対して、SSHを許可しておきます。

ターミナルからもログインしてみて問題ないことを確認しておきます。

2段階認証を有効化

こちらも簡単です。

ログイン後、画面のアカウント名にあるドロップダウンリストをクリックし、メニューから『オプション』を選択します(下記画像は admin でログインしたときのものです)。

f:id:junichim:20210921114031p:plain

『2段階認証』タブを選択し、『使用開始』をクリックします。

f:id:junichim:20210921114208p:plain

QRコードが表示されるので、

f:id:junichim:20210921114338p:plain

スマホでQRコードを読み取ります(認証アプリは Google Authenticator を使ってます)。スマホ側で設定ができたら、『次へ』ボタンを押すと、スマホに表示されるセキュリティコードを入力するように求められるので、入力して問題がなければ設定完了です。

問題発生

さて、ここまでやって問題がないように思えたのですが、一つ重大な問題が起きてました。 2台のQNAPでレプリケーションを行っているのですが、夜中に動いているレプリケーションが失敗していました。

調べてみると、レプリカジョブを設定した際に使用していたアカウントが admin だったのですが、レプリカの受信側のNASでも admin を無効にしたため、アカウント認証が失敗したのが原因でした。

ということで、新規にレプリカジョブを設定しました。

レプリカジョブのユーザー名の設定方法

下記の記事をみると、 QTS 4.5.4 以降であれば、スナップショットレプリカのユーザー名を変更できるようです。

In Snapshot Replica, why can’t my NAS connect to the remote NAS? | QNAP

ネット上のディスカッションの記事などを見ると、adminは変更できない、というのもあるのです、 QNAP の記事があるということは仕様変更があったんでしょうね、多分。

ということで、これに従って、ユーザー名を変更してみます。

新規にレプリカジョブを設定

ユーザー名を変更としましたが、実際は(後述する理由により)新規にレプリカジョブを設定しました。

送信側のNASにログインして、『ストレージ&スナップショット』を開いて『スナップショットレプリカ』を選択します。

『レプリケーションジョブの作成』を押して、レプリカジョブを設定していきます。受信側 NAS のアカウント情報として、 admin を無効にしているので、新規追加管理者のユーザー名を指定して、『テスト』を実施すると、

f:id:junichim:20211020154952p:plain

のように、受信側NASの2段階認証を無効にしろ、と出てきます。

それってセキュリティ的にどうなんだろうか?と思いつつも仕方ないので、2段階認証を無効にして、再度『テスト』を実行すると、

f:id:junichim:20211020155552p:plain

のように成功と表示されます。

あとは、ジョブを実行するスケジュールや送信時のオプション(圧縮の有無や暗号化の有無など)を選択して、ジョブを作成します(下記画面の下側のジョブです)。

f:id:junichim:20211020155907p:plain

動作確認のため、『▶』のボタンを押すとすぐにレプリカジョブが実行されます。問題なくジョブが完了すれば、OKです。

不可解な現象

上記のレプリカジョブの設定が成功するまでにいろいろと試しました。その際に不可解な現象が2点ほどあったので、メモっておきます。

現象1

上記の設定方法として、『新規にレプリカジョブを設定』としたのですが、普通に考えれば、既存のレプリカジョブのユーザー名を変更すればいいのでは?となると思います。

実は、最初はこのように既存のジョブに対して、ユーザー名を変更して試したのですが、こんな感じになぜかジョブが失敗する、というのがありました。

f:id:junichim:20211021094836p:plain

いろいろと調べたのですが、結局原因はわからずじまいでしたが、現象としては、

  • 既存のレプリカジョブのユーザー名を変更することは可能
  • 『今すぐ実行』をおこなうと、ジョブは問題なく開始する
  • しかし、ジョブの最後でエラーが発生し、レプリカジョブそのものは失敗と記録される
  • 一方、受信側NASでは、スナップショットが記録されている

というものでした。なお、送信側のレプリカジョブのログを見ると、エラーは

f:id:junichim:20211020160714p:plain

というものでした。

いろいろと試したのですが、結局、既存のレプリカジョブ(今まで動作していたジョブ)を使うとなぜか失敗する理由はわかりませんでした。ひょっとしたら、保存済みのスナップショットの絡みとかがあるのかもしれませんが、そこまで試してないので原因は不明です。

今回の自分の場合は、古いほうのスナップショットレプリカジョブと受信側NASにあるすでに取得済みのスナップショットをそのまま残しておけば、レプリカジョブ自体は新規に作っても問題なかったのでよかったのですが、もしどうしても同じジョブを使わないといけない場合はちょっと苦労しそうですね。

なお、参考までに、スナップショットレプリカでの似たような問題が、下記にも載ってました。

Snapshot Replicas and changing from Default Admin account - QNAP NAS Community Forum

現象2

これはレプリカジョブそのものの不具合というのではありませんが、ちょっと不思議な現象だったので、メモっときます。

レプリカジョブでユーザー名が admin の設定のジョブが残っている状態(adminを指定している古いジョブと新規追加管理者を指定している新しいジョブが2つある状態)で、動作確認のため NAS を2台とも再起動しました。

すると、受信側の NAS にログインすると

f:id:junichim:20211020161021p:plain

こんな感じに、『IP アドレス 192.168.x.x をブロックした』と警告メッセージが出てます。この IP アドレスは送信側のNASのものです。

実際に、『コントロールパネル』->『セキュリティ』->『許可/拒否リスト』を見ると、下記画像のように、接続拒否になっています。

f:id:junichim:20211020172850p:plain

どういうことだろうか?と思い QuLog Center を開いて、システムアクセスログを確認すると、

f:id:junichim:20211020173238p:plain

のように、 admin アカウントおよび新規追加管理者でのログインの失敗が記録されています。

ここで『コントロールパネル』の『セキュリティ』を確認すると、『IPアクセス保護』のタブに

f:id:junichim:20211020162730p:plain

とあります。1分間に5回以上 SSH でのログインに失敗があると一時的にブロックするとあります(画面の設定値はNASのデフォルト値です)。どうも、これにひっかかったようです。

どういうことでしょうか?単純に推測すると、 NAS を起動したタイミングでレプリカジョブに設定しているユーザーによりログインが試みられているのではないかと思われます。

この推測の元、いろいろやってみます。

『セキュリティ』画面から、ブロックしていた制限を削除すると、新規追加管理者のほうはログイン成功が記録されるようになりました(起動時の一時的なログイン失敗と考えればよいのかな?)。

一方、QuLog Center を確認すると、 admin アカウントのほうは引き続きログイン試行を行い、接続失敗になっています(ただし、ログを見るとログイン試行は連続で3回ほどだったので、接続拒否の試行回数5回/分に達しないためか、接続拒否には追加されなくなっていました)。

次に、送信元のレプリカジョブのユーザー名を admin から、新規追加管理者に変更したら、 admin でのログイン失敗の記録が収まりました。

なので、この一連の動作は、やはりレプリカジョブの挙動だと推測されます。

なんとなく現象がわかったのでいいんですが、いきなり接続拒否のメッセージが出てきたら焦りますね。

まとめ

結局、スナップショットレプリケーションの関係で、管理者アカウントは下記のように設定しました。

  • レプリケーションの受信側 NAS は、 admin を無効化し、新規ユーザーを作成し、2段階認証は無効にしました
  • レプリケーションの送信側 NAS は、 admin を無効化し、新規ユーザーを作成し、2段階認証を有効にしました

また、スナップショットレプリカについては、

  • admin アカウントを無効にして、レプリカジョブを設定することは可能
  • ただし、うまくいかない場合もあるので、場合によっては試行錯誤も必要かも
  • NAS の再起動時は、ログイン失敗により接続拒否になっていないことを確認したほうがベターかも

というあたりでしょうか? 検証が不十分な面もある情報ですが、一事例として何かのご参考になればと思います。

にしても、QNAP さん自身も一般的な推奨事項として、 admin は無効にしましょうと言ってるので、 admin を無効化するなら、レプリカジョブももうちょい賢く対応してほしいものです。 > QNAP さん

いずれにしても、マルウェアとか、ほんとやめてほしいですね。

Graphviz のインストール

グラフを書きたくなったので、 Graphviz をインストールしました。一連の作業時のメモです。

なお、下記の記事を参考にしています。

テキストデータをグラフ画像に変換するツール「Graphviz」ことはじめ | DevelopersIO

Graphviz のインストール

wsl ならインストールは簡単です。

mor@DESKTOP-DE7IL4F:~/tmp/graphviz$ sudo apt install graphviz

テスト

test.dot というファイルを用意します。

// graphviz test file
// ref
//   https://dev.classmethod.jp/articles/graphviz-beginner/
//
strict graph {
  a -- b
  c -- d
}

png 形式でファイルに出力します。

mor@DESKTOP-DE7IL4F:~/tmp/graphviz$ dot -Tpng test.dot -o test.png

こんな感じでグラフが作れます。

f:id:junichim:20211015115547p:plain

ただ、このままだと日本語は表示できませんでした。

日本語フォントのインストール

というわけで、日本語フォントをインストールします。wsl2 でも Ubuntu と同じようにインストールすればよいようです。

下記の記事などを参考にして、

インストールしてみます。

mor@DESKTOP-DE7IL4F:~/tmp/graphviz$ sudo apt install fonts-ipafont fonts-ipaexfont

IPA フォント IPAex フォントについては、下記などをご参考にしてください。

IPAexフォントおよびIPAフォントについて | 一般社団法人 文字情報技術促進協議会

dot ファイルでのフォントの指定方法は、こちらの記事などを参考にしました。下記の dot ファイルを処理させると、

strict graph {
  node [shape=circle, fontname="IPAexGothic"]
  a [label="あ"]

  a -- "日本語"
}

f:id:junichim:20211015121526p:plain

問題なく表示できました。

ちなみに、 fontname が実際にどのフォントを指しているかを見たければ、 -v を付ければこんな感じに表示されます。

mor@DESKTOP-DE7IL4F:~/tmp/graphviz$ dot -Tpng japanese_valid.dot -o japanese_valid.png -v
dot - graphviz version 2.43.0 (0)
(中略)
fontname: "IPAexGothic" resolved to: (PangoCairoFcFont) "IPAexGothic, Regular" /usr/share/fonts/truetype/fonts-japanese-gothic.ttf
(後略)
mor@DESKTOP-DE7IL4F:~/tmp/graphviz$ 

あとは、dotファイルの書き方を調べていけば、いろいろと書けるようになりそうです。

Unicode の全角マイナス問題にひっかかりました

SQL Server Management Studio (SSMS) を使って、 SQL Server を操作しているのですが、 SSMS ってそのままクエリを書くと Shift-JIS で保存されます。

で、いろいろあって、このクエリを Unicode (utf-8) に変換して管理しています。

ここで、 utf-8 への変換に nkf を使っていたのですが、全角マイナスが入っていると妙な文字に変換されることに気が付きました (なお、 iconv だと変換元のファイルの文字コードを指定する必要があって、それを避けたかったので、 nkf を使っています)。

このトラブルについて調べたので、せっかくなのでメモにしておきます。

なお、作業環境としては基本的に Windows 10 ですが、コマンドライン操作は wsl2 (Ubuntu 20.04) で行っています。

トラブルについて

例えば、全角マイナス1文字だけの Shift-JIS のファイルを用意して

f:id:junichim:20211014211449p:plain

mor@DESKTOP-DE7IL4F:~/tmp/jm$ xxd sample_zen_minus_sjis.txt
00000000: 817c 0d0a                                .|..
mor@DESKTOP-DE7IL4F:~/tmp/jm$

nkf を使って変換します。

mor@DESKTOP-DE7IL4F:~/tmp/jm$ nkf -w sample_zen_minus_sjis.txt > sample_zen_minus_utf8_w.txt

中身を見てみると

f:id:junichim:20211014211556p:plain

mor@DESKTOP-DE7IL4F:~/tmp/jm$ xxd sample_zen_minus_utf8_w.txt
00000000: e288 920d 0a                             .....
mor@DESKTOP-DE7IL4F:~/tmp/jm$

となります。微妙に半角マイナスっぽい感じになってますね(Unicode 表記だと U+2212 なので半角マイナスとは違いますね)。

検証のために、テキストエディタ(サクラエディタ)で、全角マイナスを入力してutf-8で保存すると、

f:id:junichim:20211014211746p:plain

mor@DESKTOP-DE7IL4F:~/tmp/jm$ xxd sample_zen_minus_utf8_editor.txt
00000000: efbc 8d0d 0a                             .....
mor@DESKTOP-DE7IL4F:~/tmp/jm$

となり、 Unicode 表記で U+FF0D となるので、先ほどの nkf による変換後のファイルの中身が全角マイナスとは違っていることがわかります。

さて、これはどういうことなんでしょうか?

原因と解決方法

これ、全然知らなかったのですが、下記の記事で書かれているように、有名な問題だったようです。

UTF-8における全角マイナスと全角チルダの問題(=いわゆる「波ダッシュ問題」) - 半径5メートル

この記事内からも参照されていますが、Wikipedia にも記載があります。

Unicode - Wikipedia

Wikipedia のほうには文字コードも載っているので、それと合わせると上記の変換結果と対応することがわかります。

結局、原因としては、仕様、ということのようです。

まあ、仕様なのはしょうがないのですが、一緒に解決法も載っていました(ありがたいです)。

nkf の場合は -w ではなく --ic と --oc を使って入力の文字コードを指定すればよいそうです。 なるほど。 Wikipedia の説明を踏まえると、 nkf の場合、 Shift-JIS から Unicode へ変換するのと CP932 から Unicode へ変換するので、変換先が違うんですね。

試してみます。

mor@DESKTOP-DE7IL4F:~/tmp/jm$ nkf --ic=cp932 --oc=utf8 sample_zen_minus_sjis.txt > sample_zen_minus_utf8_icoc.txt

ダンプしてみると

mor@DESKTOP-DE7IL4F:~/tmp/jm$ xxd sample_zen_minus_utf8_icoc.txt
00000000: efbc 8d0d 0a                             .....
mor@DESKTOP-DE7IL4F:~/tmp/jm$

おお、さっき、テキストエディタで保存した場合と一致しましたね。問題ないです。

ちなみに、iconv の場合も試しましたが、

mor@DESKTOP-DE7IL4F:~/tmp/jm$ iconv -f sjis -t utf8 sample_zen_minus_sjis.txt > sample_zen_minus_utf8_iconv.txt
mor@DESKTOP-DE7IL4F:~/tmp/jm$ xxd sample_zen_minus_utf8_iconv.txt
00000000: e288 920d 0a                             .....
mor@DESKTOP-DE7IL4F:~/tmp/jm$
mor@DESKTOP-DE7IL4F:~/tmp/jm$ iconv -f cp932 -t utf8 sample_zen_minus_sjis.txt > sample_zen_minus_utf8_iconv_cp932.txt
mor@DESKTOP-DE7IL4F:~/tmp/jm$ xxd sample_zen_minus_utf8_iconv_cp932.txt
00000000: efbc 8d0d 0a                             .....
mor@DESKTOP-DE7IL4F:~/tmp/jm$

となるように、入力ファイルの文字コードを sjis と指定すると nkf と同じ問題が起きますね(解決法も同じ)。

にしても、こんな問題があるなんて、やっぱり文字コードは怖いですね。