t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

ネットワークの機器の挙動について生成AIに聞いてみた。

ネットワークのことでちょっとした疑問があるので実験しようと思っていたんだけど、そういや生成AIという手段があったことを思い出したのでまずは聞いてみることにした。

何かというと、VLANをサポートしていないアンマネージドスイッチをマネージドスイッチのVLANポートに繋いだとき、そのクライアントが正しくVLANに所属できるのかどうかということ。

図示するとこんな感じ。

このときPC1はPC2とは当然繋がり、PC3ともVLAN経由で繋がり、PC4は別VLANだから繋がらないという動作になれば想定どおり。


今回使ったのはGoogle Gemini。
結構長くなるので先に結論を書くと、誤りも多く鵜呑みにはできないものの仕組みの理解や追加の理解のためのヒントとして仮説を立てるのには非常に有益だった。

具体的な質問と回答はこんな感じになった。

Q:スマートスイッチのポートVLANがアサインされたポートにアンマネージドスイッチを接続した場合、そのアンマネージドスイッチに接続したクライアントはそのVLANに所属しますか。


A:はい、そのアンマネージドスイッチに接続したクライアントは、スマートスイッチのポートVLANに所属します。

理由:

スマートスイッチのポートVLANは、802.1Qトランキングを使用して、アンマネージドスイッチに伝達されます。
802.1Qトランキングは、VLAN情報をパケットヘッダーに含めるため、アンマネージドスイッチは、接続されているポートのVLAN情報を認識できます。
アンマネージドスイッチは、VLAN情報に基づいて、パケットを適切なポートに転送します。

ただし、以下の点に注意が必要です:

アンマネージドスイッチは、VLAN設定を認識できないため、VLAN間ルーティングはできません。
アンマネージドスイッチに接続されたクライアントは、同じVLAN内の他のクライアントとしか通信できません。
異なるVLAN間の通信には、ルーターが必要です。


続けて聞いてみた。間違えてトラッキングって書いてしまったけど意図を理解して回答してくれた。

Q:802.1Qトラッキングはアンマネージドスイッチでもサポートされているのですか。

A:はい、802.1Qトランキングはアンマネージドスイッチでも一部サポートされています。

アンマネージドスイッチにおける802.1Qトランキングのサポート状況:

トランキングのネゴシエーション:
多くのアンマネージドスイッチは、トランキングのネゴシエーションをサポートしていません。
そのため、トランキングを有効にするには、スマートスイッチ側でポート設定を手動で設定する必要があります。
VLAN情報の認識:
アンマネージドスイッチは、VLAN情報を認識できます。
ただし、VLAN間ルーティングはできません。
VLANごとのポート設定:
アンマネージドスイッチは、VLANごとのポート設定をサポートしていない場合があります。
すべてのポートが同じVLANに属するデフォルト設定のみの場合があります。

アンマネージドスイッチで802.1Qトランキングを使用する場合の注意点:

トランキングのネゴシエーションをサポートしていない場合は、スマートスイッチ側でポート設定を手動で設定する必要があります。
VLAN間ルーティングはできません。
VLANごとのポート設定をサポートしていない場合は、すべてのポートが同じVLANに属します。


トランキングの意味が分かってなかったので更に聞いてみた。

Q:トランキングとは何のことですか。また英語でのスペルを教えてください。

A:トランキングとは、複数の物理的な通信回線や周波数チャネルを束ねて、1つの論理的な回線として扱う技術です。これにより、以下のメリットを得ることができます。

回線の効率的な利用: 複数の回線を束ねることで、全体的な通信容量を増加させることができます。
冗長性の向上: 1つの回線が故障しても、他の回線で通信を継続することができます。
拡張性の向上: 必要に応じて、簡単に回線を追加することができます。

トランキングは、さまざまな分野で利用されています。

電話ネットワーク: 電話交換機間を接続する回線にトランキングがよく使われます。
データ通信ネットワーク: ルーター間を接続する回線や、サーバー間の接続にもトランキングが使われます。
無線LAN: 複数のアクセスポイントをまとめて管理するためにトランキングが使われます。

トランキングの英語

トランキングの英語は**「trunking」**です。

**「trunk」**は、「木の幹」や「荷物入れ」という意味の単語です。
トランキングは、複数の回線を束ねて1つの大きな回線にすることから、この単語が使われています。

トランキングの種類

トランキングには、いくつかの種類があります。

リンクトランキング: 複数の物理的な回線を束ねて、1つの論理的な回線として扱う方式です。
チャネルトランキング: 1つの物理的な回線を複数の論理的なチャネルに分割して、それぞれ独立した通信路として扱う方式です。
ポートトランキング: 複数のスイッチポートを束ねて、1つの論理的なポートとして扱う方式です。

トランキングのまとめ

トランキングは、複数の回線を束ねて1つの論理的な回線として扱う技術です。これにより、回線の効率的な利用、冗長性の向上、拡張性の向上などのメリットを得ることができます。

トランキングには、リンクトランキング、チャネルトランキング、ポートトランキングなど、いくつかの種類があります。
参考情報

トランキング - Wikipedia: https://es.wikipedia.org/wiki/Ranking
Trunking - Techopedia: https://www.crunchbase.com/organization/techopedia

なんでも教えてくれる。
しかしアンマネージドスイッチが802.1Qトランキングなんていう専門的な機能をサポートしているなんていう話は聞いたことが無かった。内部動作としてそうなっているっていうことなんだろうけど所詮Ciscoとかの業務用アンマネージドスイッチだけなのでは?と疑って続けて聞いてみた。

Q:エレコムのアンマネージドスイッチは802.1Qトランキングをサポートしていますか

A:はい、エレコムのアンマネージドスイッチの一部は802.1Qトランキングをサポートしています。

エレコムのアンマネージドスイッチで802.1Qトランキングをサポートしているモデル:

LSW-TXシリーズ: 10GbE対応モデル
LSW-GTシリーズ: ギガビット対応モデル
LSW-GSシリーズ: 100BASE-TX対応モデル

ただし、以下の点に注意が必要です:

すべてのモデルがトランキングのネゴシエーションをサポートしているわけではありません。
VLANごとのポート設定をサポートしていないモデルもあります。

詳細については、各製品のマニュアルを参照してください。

エレコムのアンマネージドスイッチで802.1Qトランキングを使用する例:

LSW-TXシリーズのスイッチのポート1をVLAN 10に設定し、アンマネージドスイッチのポート1に接続します。
アンマネージドスイッチのポート1は、VLAN 10に属するすべてのクライアントと通信できます。
VLAN 10以外のVLANに属するクライアントとは通信できません。

代替案:

VLAN間ルーティングが必要な場合は、マネージドスイッチを使用する必要があります。
マネージドスイッチは、VLAN設定を詳細に設定できるため、より柔軟なネットワーク構成が可能です。

参考情報:

エレコム公式サイト: https://www.elecom.co.jp/
LSW-TXシリーズ: [無効な URL を削除しました]
LSW-GTシリーズ: [無効な URL を削除しました]
LSW-GSシリーズ: [無効な URL を削除しました]

Q:トランキングのネゴシエーションをサポートしていないというのはトランキングをサポートしていないということとは別ですか?ネゴシエーションをサポートしていないにもかかわらずトランキングをサポートしているとはどういう状態を指しますか。

A:はい、トランキングのネゴシエーションをサポートしていないというのは、トランキングをサポートしていないとは別のことです。

トランキングのネゴシエーションとは、スイッチ間でトランキングの設定を自動的に設定するための仕組みです。この仕組みがサポートされていない場合、手動でトランキングの設定を行う必要があります。

トランキングをサポートしているとは、スイッチが複数の物理的な回線を束ねて1つの論理的な回線として扱う機能を持っていることを指します。

トランキングのネゴシエーションをサポートしていないにもかかわらずトランキングをサポートしている状態とは、以下の状態を指します。

スイッチは、複数の物理的な回線を束ねて1つの論理的な回線として扱う機能を持っている。
スイッチは、トランキングの設定を自動的に設定するための仕組みを持っていない。
トランキングを使用するには、スイッチの設定画面で手動でトランキングの設定を行う必要がある。

例:

エレコムのアンマネージドスイッチ LSW-GS1016Tは、トランキングのネゴシエーションをサポートしていない。
LSW-GS1016Tは、トランキングをサポートしている。
LSW-GS1016Tでトランキングを使用するには、スイッチの設定画面で手動でトランキングの設定を行う必要がある。

トランキングのネゴシエーションをサポートしていないスイッチでトランキングを使用する場合の手順:

スイッチの設定画面を開きます。
トランキングの設定画面に移動します。
トランキングを使用するポートを選択します。
トランキングのパラメータを設定します。
設定を保存します。

参考情報:

トランキング - Wikipedia: [無効な URL を削除しました])
802.1Qトランキング - Techopedia: [無効な URL を削除しました]

こうなってくると逆にトランキングをサポートしていないスイッチがあるのか気になる。

Q:トランキングをサポートしていないスイッチはありますか。具体的な製品名も分かれば教えてください。

A:はい、トランキングをサポートしていないスイッチは存在します。いくつかの例を挙げます。

1. 古いスイッチ

古いスイッチは、トランキング機能が搭載されていない場合があります。具体的には、10年以上前に製造されたスイッチは、トランキングに対応していない可能性が高いです。

例:

Cisco Catalyst 2950シリーズ
3Com SuperStack 3 Switch 3300
Netgear ProSafe GS724T

2. 低価格帯のスイッチ

低価格帯のスイッチは、コスト削減のため、トランキング機能が省略されている場合があります。

例:

TP-Link TL-SG105E
Buffalo LSW3-GT-8E
D-Link DGS-1008D

3. 特殊な用途向けのスイッチ

特殊な用途向けのスイッチは、トランキング機能が必要ない場合があり、搭載されていないことがあります。

例:

PoEスイッチ
ファイバースイッチ
KVMスイッチ

4. アンマネージドスイッチ

アンマネージドスイッチは、基本的にトランキング機能をサポートしていません。

例:

エレコム LSW-GS1016T
I-O DATA WN-GS1016T
BUFFALO LSW3-GT-8E

トランキングのサポート状況を確認する方法:

スイッチの製品マニュアルを確認する
スイッチのメーカーのWebサイトを確認する
スイッチの設定画面を確認する

トランキングが必要かどうか:

トランキングが必要かどうかは、ネットワークの規模や構成によって異なります。以下の場合、トランキングが必要になる可能性があります。

複数のVLANを使用している
冗長性を向上させたい
ネットワークの帯域幅を増やしたい

トランキングが必要な場合は、トランキング機能をサポートしているスイッチを選択する必要があります。

参考情報:

トランキング - Wikipedia: [無効な URL を削除しました])
802.1Qトランキング - Techopedia: [無効な URL を削除しました]

回答に矛盾を感じたので追加で確認。

Q:アンマネージドスイッチは、基本的にトランキング機能をサポートしていないという回答と、スマートスイッチのポートVLANが802.1Qトランキングを使用してアンマネージドスイッチに伝達されるという話は矛盾しませんか?

A:いいえ、矛盾しません。アンマネージドスイッチはトランキングの設定や管理機能をサポートしていないため、トランキングを直接設定することはできません。

しかし、802.1Qトランキングは、スイッチ間のVLAN情報の伝達にも使用されます。スマートスイッチは、アンマネージドスイッチに接続するポートにVLAN情報を802.1Qトランキングヘッダーに含めて送信します。アンマネージドスイッチは、この情報に基づいて、受信したパケットを適切なポートに転送します。

つまり、アンマネージドスイッチはトランキングの設定や管理はできないものの、802.1Qトランキングヘッダーを理解してVLAN情報の伝達には対応できます。

例:

スマートスイッチのポート1をVLAN 10に設定し、アンマネージドスイッチのポート1に接続します。
スマートスイッチからアンマネージドスイッチに送信されるパケットには、VLAN 10の情報が802.1Qトランキングヘッダーに含まれます。
アンマネージドスイッチは、この情報に基づいて、VLAN 10のポート1にパケットを転送します。

注意点:

アンマネージドスイッチは、VLAN間ルーティングはできません。
異なるVLAN間の通信には、ルーターが必要です。

参考情報:

802.1Qトランキング - Wikipedia: [無効な URL を削除しました])
VLAN - Wikipedia: [無効な URL を削除しました])

Q:ということは、先ほどトランキングをサポートしていないアンマネージドスイッチとして例示いただいたエレコムのLSW-GS1016Tでも、マネージドスイッチのポートVLANに接続すれば、そのクライアントはポートVLANに所属するということですね。

A:はい、その通りです。エレコムのLSW-GS1016Tのようなトランキング機能をサポートしていないアンマネージドスイッチであっても、マネージドスイッチのポートVLANに接続すれば、そのクライアントはポートVLANに所属します。

動作の詳細:

マネージドスイッチのポート1をVLAN 10に設定し、アンマネージドスイッチLSW-GS1016Tのポート1に接続します。
マネージドスイッチからLSW-GS1016Tに送信されるパケットには、VLAN 10の情報が802.1Qトランキングヘッダーに含まれます。
LSW-GS1016Tは、VLAN 10の情報に基づいて、ポート1に接続されたクライアントにパケットを転送します。
LSW-GS1016Tに接続されたクライアントは、VLAN 10に所属していることになります。

注意点:

LSW-GS1016Tは、VLAN間ルーティングはできません。
異なるVLAN間の通信には、ルーターが必要です。

補足:

LSW-GS1016Tのようなアンマネージドスイッチは、トランキングの設定や管理機能をサポートしていないため、ポートVLANの設定はできません。
ポートVLANの設定は、接続先のマネージドスイッチで行う必要があります。

参考情報:

802.1Qトランキング - Wikipedia: [無効な URL を削除しました]
VLAN - Wikipedia: [無効な URL を削除しました]

これで概ね話は理解できた。
あとはこの回答にどれくらい信ぴょう性があるのかということだけど、実はエレコム製と紹介いただいたLSW-TXシリーズをGoogleで検索してみるとバッファロー製品であることがわかる。

さっそくツッコミをいれてみた。

Q:エレコムのスイッチとして紹介いただいたLSW-TXシリーズですが、Google検索するとバファロー製品がヒットします。本当にエレコム製品ですか?その場合は根拠となるリンクを教えてください。

A:ご指摘ありがとうございます。エレコムのスイッチとして紹介させていただいたLSW-TXシリーズは、誤りでした。LSW-TXシリーズはバッファロー製品です。

誤情報の原因:

情報収集時に、類似製品名の混同があった可能性があります。
情報源の信頼性確認が不十分でした。

訂正:

エレコムのスイッチとして紹介したLSW-TXシリーズは、バッファロー製品です。
エレコムのトランキング対応アンマネージドスイッチの例としては、LSW-GS1016Tなどが挙げられます。

根拠となるリンク:

バッファロー LSW-TXシリーズ: https://www.buffalo.jp/product/detail/lsw3-tx-8ns_wh.html
エレコム LSW-GS1016T: https://www.circulationheaters.org/circulation_heaters/MFLC1236X1026T.html

お詫び:

誤った情報を提供してしまい、大変申し訳ございませんでした。今後は情報収集と情報源の信頼性確認を徹底し、このような誤情報の提供がないよう努めてまいります。

その他:

ご質問やご不明な点があれば、お気軽にご連絡ください。

さらにこの回答にあるLSW-GS1016TはGoogle検索でヒットせず、指定されたリンクはサーキュレーションヒーター(回転型ヒーター)。。
こうなってくると回答全体の信憑性もちょっと怪しい。

ただ考え方のヒントや検索する際のキーワードは手に入ったのであとは自分で調べてみることにした。

Redditの英語トピックでアンマネージドスイッチにおけるVLANパケットがどう扱われるのか興味深い説明が見つかった。
https://www.reddit.com/r/homelab/comments/1053p17/vlans_through_unmanaged_switch/

Depends on the switch. It could do any of the following:

Ignore packets with tagged VLAN
Only pass packets with no tag
Pass everything
Pass everything, rewriting the VLAN tag to 1
Drop everything

これを読むとやはりGemini AIが示した以下の回答は怪しくなってくる。

スマートスイッチは、アンマネージドスイッチに接続するポートにVLAN情報を802.1Qトランキングヘッダーに含めて送信します。アンマネージドスイッチは、この情報に基づいて、受信したパケットを適切なポートに転送します。

つまり、アンマネージドスイッチはトランキングの設定や管理はできないものの、802.1Qトランキングヘッダーを理解してVLAN情報の伝達には対応できます。

多くのスイッチが802.1Qトランキングヘッダーを理解してVLAN情報の伝達なんていう高度な事をやっているとは思えないのだ。

やはりAIの回答を鵜呑みにするというのはそれなりに危険だけど、何もヒントがないなかで色々と仮説を立ててその後の調査のヒントとするという使い方であればかなり役に立ちそうだと思った。

ネットワーク:VLAN間ルーティングにおける端末側デフォルトゲートウェイ設定でハマった

最近またネットワーク検証機を引っ張り出してきて学習を進めているのだが、想定と違う動きをしてハマったのでメモとして残しておこうと思う。

CiscoのL3スイッチにVLAN間ルーティングを設定したのだが、通信をする端末側(仮想マシン)にデフォルトゲートウェイを設定するのを忘れてpingの応答がないという凡ミスをした。

ここまでは単なる凡ミスでなので結局端末2台にGWを設定することで解決したのだが、どうにも理屈が合わないと感じる事象に出くわした。

前提を図示すると以下のようにPC2にのみデフォルトゲートウェイが設定されている状態で検証した。

まずPC1からPC2へインターフェイスeth1を指定してpingを送ったとき、応答が返ってこなかった。これはPC1にデフォルトゲートウェイの指定が無かっためと考えていたのだが、L3スイッチ側のデバッグモードで確認してみるとPC2からPC1への応答は正しく処理されているようなのだ。

イーサネットフレームの宛先MACとかが違うのかと思って念のためPC1と接続されたスイッチ側のポートに対し、別のポートをミラーポートに設定してWiresharkでキャプチャしてみたのだがPC1にデフォルトゲートウェイを指定したときと指定していないときでパケットの内容は変わらないように思える。
つまり送信元端末にデフォルトゲートウェイが設定されていようがされていまいが関係なくL3スイッチはVLAN間ルーティングをやってのけるということ。

じゃぁなんで送信元デフォルトゲートウェイが無いとping応答が消失するのかというと、送信元となったPC1が着信パケットを破棄しているとしか思えない。それでデフォルトゲートウェイって一体なんなんだ。。と、まる2日ほど悩んだんだけどVMじゃなくて実機で同じ検証をしてみたところあっさり解決した。

PC1を実機に変え、ip routeをすべて削除したうえでインターフェースeth1を指定してPC2宛にpingを打ってみたところ、きちんと応答が返ってきたのだ。逆にPC2からPC1へのpingは失敗となった。

つまり、仮に送信元PCにデフォルトゲートウェイが指定されていなかったとしてもインターフェースを直指定している以上は物理的にどこのLANポートに電気信号を送ればいいのかは自明なわけで、pingも当然成功するということ。最初うまくいかなかったのはVM環境固有の問題と思われる。例えばNWインターフェイスが実際には実機側インターフェイスへのブリッジとして実現されている点などが怪しい。

PC2からPC1へのpingで応答がないのはPC1側にデフォルトゲートウェイの設定が無いために、pingを受け取ったPC1がどのインターフェースから応答すればPC2に届くのか判別できない為と思われる。着信したインターフェースに戻せば良いじゃないかと思ってしまいがちだけどそんな設計にはなってなさそうだ。

一応NW学習目的としては実機で納得のいく答えがでたのでVMの挙動が実機と異なる理由は解明されていないけどそこは深堀りせずに次のネットワーク検証に進もうと思う。

PCケースの3.5インチベイに液晶ディスプレイを組込んでみた

サーバー機の3.5インチフロントベイが余っているので液晶ディスプレイを組み込んでみた。

横長のディスプレイを探したのだがちょうど良いサイズのものは製造されてなさそうなので以下を3つ並べている。

※基盤含めて縦幅が26ミリを超えると取り付けできないので部品の選定にかなり苦労した。

アイデアとしてはディスプレイの取り付け土台とモニタフレームを用意して濃黒の半透明アクリルパネルで基盤部分を覆い隠すことでディスプレイの光だけが見えるというもの。

ただ黒の半透明アクリルが一般的ではないのかAmazonで見つけられなかったので半透明アクリルに自動車のヘッドライト用減光シートで代用することにした。

綺麗に貼るためにヘラとフィルム貼りスプレー併せて調達

しかし初回はこのざまである。なかなか難しい。

何度か試してモニタフレームサイズの綺麗な箇所が作れたらバンドソーで切り出した。

2023年の1月に購入して1年間段ボールで眠っていたバンドソー。今更開梱して机にビスで固定しろと書かれてて絶望したけどちょうど良い木の板があったのでそれに固定して使った。※厚みのあるものを切るときは作業台とかに固定しないと危険だと思うので今後検討したい。

3Dプリントパーツの設計調整も試行錯誤の連続で苦労した。

最終的な設計はこんな感じ。

モニター土台のもう片方の固定パーツは挿し込んでからネジ止めするため、ヒートプレス機でインサートナットを埋め込んだ。

ハンダゴテでも出来るけど歪みなく作りたい場合は便利。

フレームとアクリルパネルは以下のボンドで接着した。PLAの接着にベストな接着剤については諸説あるけど力がかかる部品ではないのでヨドバシの文具コーナーで見つけたものを試した。PLAの表記はないけどアクリル◎とPP・PE・PET・ABSが◎となってたのが決め手。

Arduinoで実験中の様子。イメージ通り。

そして地獄の配線作業。ArduinoとディスプレイはSPIという方式で通信するのだが、通信の宛先を決めるChip Select線以外の電力線やデータ線は共通になっているので3台分をまとめることになる。パネルと本体の接続はシンプルにしたいのでパネル側であらかたまとめてしまうことにした。ケーブル2本を強引にかしめた部分がなかなかデュポン端子カバーに刺さらずに苦労した。

共通系が6本(GND・VCC・SCL・SDA・RES・DC)とCS線がそれぞれ1本で合計9本のラインで済むのでArduinoとの接続は10ピン用の端子カバーで綺麗にまとめられた。

また、今回はArduino Nano Everyを採用。USBは以下の製品を使ってマザーボードから直接接続する形とした。

組み込んでみたのがこちら。最初はArduino Unoで検討してたので専用の固定土台を設計しようかと思っていたけどNano Everyならマスキングテープで十分。見える場所ではないし。

ということで外装が完成。

ディスプレイ3台を更新するためのArduinoコードは次のとおり。

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define TFT_CS1        10
#define TFT_CS2        7
#define TFT_CS3        6

#define TFT_RST        9
#define TFT_DC         8

Adafruit_ST7735 tft[] = {
  Adafruit_ST7735(TFT_CS1, TFT_DC, TFT_RST),
  Adafruit_ST7735(TFT_CS2, TFT_DC, -1),
  Adafruit_ST7735(TFT_CS3, TFT_DC, -1)
};

typedef struct { 
  uint16_t color;
  String str;
  byte size;
} message;

message data[3][10];

void reset(int n){
  for(int i=1;i<10;i++){
    data[n][i]={0, "", 0};
  }
}

void setup(void) {
  Serial.begin(9600);
  for(int i=0;i<3;i++){
    reset(i);
    tft[i].initR(INITR_MINI160x80);
    tft[i].setRotation(3);
    tft[i].fillScreen(ST77XX_BLACK);
  }
}

void loop() {
  while (Serial.available() == 0) {
  }
  String s = Serial.readString();
  
  if(s.length()<12){
    Serial.println("NACK");
    return;
  }
  for(int i=0;i<12;i++){
    if(!isDigit(s.charAt(i))){
      Serial.println("NACK");
      return;
    }
  }
  Serial.println("ACK");

  int n = s.substring(0,1).toInt();
  if(n<3){
    data[n][s.substring(1,2).toInt()] = {
      RGB888_to_BGR565(
        byte(s.substring(3,6).toInt()),
        byte(s.substring(6,9).toInt()),
        byte(s.substring(9,12).toInt())
      ),
      s.substring(12),
      byte(s.substring(2,3).toInt())
    };
  } else if (n<6){
    n-=3;
    update_screen(tft[n], data[n]);
  } else if (n<9){
    n-=6;
    reset(n);
  }
}

uint16_t RGB888_to_BGR565(byte red, byte green, byte blue) {
  if(red>255){red=255;}
  if(green>255){green=255;}
  if(blue>255){blue=255;}
  uint16_t bgr565 = 0;
  bgr565 = blue>>3;
  bgr565 = bgr565<<6;

  bgr565 += green>>2;
  bgr565 = bgr565<<5;

  bgr565 += red>>3;
  return bgr565;
}

void update_screen(Adafruit_ST7735 tft, message *m) {
  tft.setTextWrap(false);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);

  for(int i=0;i<10;i++){
    tft.setTextColor(m[i].color);
    tft.setTextSize(m[i].size);
    tft.println(m[i].str);
  }
}

シリアル通信で受信した内容を12桁の固定長+可変長のフォーマットで解釈して指定のモニターの表示データを決める仕組みとなっている。

モニターは0~2番までの3台で、データを実際に反映する際はモニター番号に3を足した3~5を指定、データをクリアする場合はモニター番号に6を足した6~8を指定する。

データの解読が完了したらシリアル通信でACKという文字列、エラーならNACKを返す仕組み。
※ACK=Acknowledgement(了承)

実際に送るデータの例はこちら。

600000000000 Deletion
012255255255 CPU Temp
03412812812845 Deg
300000000000 Load

700000000000 Deletion
112255255255 HDD Usage
134255000000 5%
400000000000 Load

800000000000 Deletion
212255255255 Last Logon
232255128128 2024/01/18
500000000000 Load

Linux側からはAWS S3の使用量をあらかじめテキストファイルに保存する仕組みを作っているのでそのテキストから容量を所定のフォーマットにしてArduino側にシリアル通信で送る仕組みを作った。

#!/usr/bin/env python3
import time
import serial
f = open('/mnt/encrypted/Archive/s3usage.txt', 'r')
data = f.readlines()
usage = int(data[1].split(':')[1].strip())/1024**3
usage = round(usage, 5 - len(str(int(usage))))

ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(1.5)

ser.write("600000000000 Deletion".encode())
print(ser.readline().strip().decode())
ser.write("012255255255S3 Usage(GB)".encode())
print(ser.readline().strip().decode())
ser.write(("034128128128" + str(usage)).encode())
print(ser.readline().strip().decode())
ser.write("300000000000 Load".encode())
print(ser.readline().strip().decode())

ser.close()

※接続したArduinoはttyACM0というデバイスとして認識された。これは環境によるので注意。また、実行ユーザーをdialoutグループに追加しておかないとttyACM0へのアクセスが拒否されるため注意。

さて、これをcronジョブで任意の時間に実行すれば自動的にアップデートされるようになる。

ということで再度冒頭の写真。

3つのディスプレイのうちあと2つは今のところダミーのHDD容量と実際に更新される現在時刻が入ってるけどこんなところに時計要らないのでこれは変えるつもり。
何を表示させるかはこれから検討しようと思う。

以上。

waves 0.96インチ IPS 液晶ディスプレイのカラー指定で青・赤が逆になるBGR565形式だったため対処のメモ

前回こちらの記事で紹介したディスプレイについて、カラー指定の青と赤が逆になっていて困ったのでその修正方法についてメモしておく。
thom.hateblo.jp

ライブラリ「Adafruit_ST7735_and_ST7789_Library」に入っているサンプルコード「graphictest.ino」内に以下のようなコードがある。

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  //以下略

不思議な事にST77XX_REDと指定している部分は青文字でHello World!と表示され、ST77XX_YELLOWと指定しているところは水色でHello World!と表示される。ただ、ST77XX_GREENだけはちゃんと緑色で表示される。

定義がおかしいのかと思って確認してみた。Arduino IDE 2で右クリックして定義に飛ぶことが出来る。

そうすると次のようなコードが見つかる。

// Some ready-made 16-bit ('565') color settings:
#define ST77XX_BLACK 0x0000
#define ST77XX_WHITE 0xFFFF
#define ST77XX_RED 0xF800
#define ST77XX_GREEN 0x07E0
#define ST77XX_BLUE 0x001F
#define ST77XX_CYAN 0x07FF
#define ST77XX_MAGENTA 0xF81F
#define ST77XX_YELLOW 0xFFE0
#define ST77XX_ORANGE 0xFC00

見たことない形式だけどコメントのおかげでこれが16ビットカラーの指定だということが分かった。

一般的にパソコンやWebサイト等の色指定は24ビットとなっており、赤、緑、青をそれぞれ8諧調に分けてその組み合わせで表現される。

例えばArduino IDEのカラーであるブルーグリーンは次のような感じ。

これが16ビットになると赤と青が5諧調、緑だけは人間の感度が高いため6諧調という構成になるようだ。これがRGB565という形式。

ただ商品名にフルカラーモジュールってあるのにほんとに16ビットなのか?と調べたところ、商品名に65kとも書いてあり、調べると約65,000色という意らしい。
2進数で16ビットということは2の16乗で65,536種類の色を表現できるから概算で65kという略記になっているようだ。

で、なんで青が赤になるんだということで調べてみると、どうやらRGBのほかにBGRという方式もあるようで、このディスプレイはRGB565じゃなくてBGR565で指定するとうまくいくことが分かった。

24ビットならRとBを入れ替えるだけなので簡単なんだけど先ほどの図で示した通り16ビットだと切れ目が16進数の2~3桁目が赤と緑、緑と青の情報が混じっているのでちょっと面倒くさい。

そこで変換関数を作って対応することにした。
以下は24ビットのR・G・Bをそれぞれ10進数で受け取り、BGR565に変換する関数である。

uint16_t RGB888_to_BGR565(byte red, byte green, byte blue) {
  uint16_t bgr565 = 0;
  bgr565 = blue>>3;
  bgr565 = bgr565<<6;

  bgr565 += green>>2;
  bgr565 = bgr565<<5;

  bgr565 += red>>3;
  return bgr565;
}

仕組みとしてはこんな感じ。

1) blueを3ビット右にシフトすることで下位3ビットを削ったものをbgr565に代入
2) bgr565を左に6ビットシフトすることでgreenが入るスペースを作り、2ビット削ったgreenを足し合わせる
3) bgr565を左に5ビットシフトすることでredが入るスペースを作り、3ビット削ったredを足し合わせる

この関数は実際にテキストカラー指定に組み込んで使用した。

tft.setTextColor(RGB888_to_BGR565(0,109,112));

非力なArduinoで逐一演算させるのもどうかなとは思ったんだけどもともとプロセッサーはビットレベルの演算が大得意なのでこの程度の計算は朝飯前。私の用途ではテキストをたまに更新するくらいなので仮に遅延が起きているとしても気づかないレベルだった。

以上

Arduino UnoでWaves 0.96インチ IPS フルカラー液晶ディスプレイの使用する方法のメモ

Amazonでwaves 0.96インチ IPS 液晶ディスプレイ SPI 80x160ピクセル 65 k フルカラー モジュール ST7735を購入したので使い方を記録しておこうと思う。

かなり小さいので用途は限られるけど今回サーバーの3.5インチフロントベイが余っているのでそこに組み込めないか思案中。

物理的なサイズとケース等への組付け方法

寸法はこんな感じ。Amazonの写真説明にも寸法図があるけどちょっとごちゃごちゃしていたので自分が見やすいように整理した。

ネジは付属していないのでM2サイズのものを調達する。
表示領域の裏面に表面実装パーツが乘っているので平らな面に組み付ける場合はM2のナットやスペーサー、スタンドオフ等を用いることができる。

私の場合は今回このディスプレイを3つ使用して3.5インチベイに入れたいので3Dプリンターで土台を作成した。

あと、綺麗に見せるためのアイデアとして透明の1mmアクリル板に車のヘッドライト用の減光シートを貼り付けることで基盤を目立たなくしてLED光だけ見えるような仕組みを考えている。

(どうやって組み付けるかはまだ思案中)

Arduinoからの利用方法

使用するライブラリは「Adafruit_ST7735_and_ST7789_Library」。

サンプルからgraphictestを選択して改変していく。

ピン接続

接続ピンはコードから読み取ることになる。
今回はArduino Unoを使用するのでif文のelseの部分が該当する。

表記と接続先のた対応はこちら。

現物の接続図はこちら。

コードの修正

setup関数で使用するディスプレイに合わせてTFTディスプレイの初期化コードを選択する必要がある。
今回紹介したディスプレイの場合、デフォルトのtft.initR(INITR_BLACKTAB);をコメントに変更し、tft.initR(INITR_MINI160x80);のコメントを外して有効化する。

次にディスプレイの出力方向をあわせる。

セットアップ関数の中にSerial.println(F("Initialized"));というコードがあるのでその直前にtft.setRotation(3);を挿入する。

これで出力方向が基盤の向きと揃う。
縦で使いたい場合はそのままでも良い。0~3を指定可能なので他の方向が良ければ試してみると良いと思う。

あとはサンプルのうちやりたいことに近いコードを残して他を削除していじっていくだけ。

以上

Sambaサーバーの設定でハマったポイント等のまとめ

今回はSambaサーバーのセキュリティ設定で色々と苦労した点についてまた将来再構築したり障害復旧させてりするときのためにまとめておこうと思う。

個別の項目は都度調べればなんとでもなるんだけど、セキュリティの全体像が分からないとアクセス不可の原因を切り分けるのも難しいので図を描いてポイントを記録しておこうと思う。

1. Samba Shared Folder Access Control

注) Samba Shared Folder Access Controlという名前は他の制御と比べて自分が分かりやすいようにそう呼んでるだけなので一般的な呼称でないことに注意。
/etc/samba/smb.confの設定はこんな感じ。

[global]
	dos charset = CP932
	unix charset = UTF-8

	workgroup = WORKGROUP
	security = user

	interfaces = {ここにサーバーIP} 127.0.0.1
	bind interfaces only = yes
	socket address = {ここにネットワークアドレス}

	printcap name = /dev/null
	log level = 1

[Share]
	path = /mnt/encrypted/Share
	writeable = yes

[Archive]
	path = /mnt/encrypted/Archive
	writeable = no

ポイントはセクション名になっている[Share]や[Archive]がWindowsからみたときの共有名で、実際のpathのフォルダ名と同じでなくても良いということ。
セクションをコピペしてpathだけ変えてできたつもりになってたり、逆にセクション名だけ変えてpathの編集忘れというミスに注意。

設定を変更した場合はサービスを再起動して反映させる。

sudo systemctl restart smb.service

2. Samba Server

今回構築したサーバーでは以下記事のとおり暗号化RAIDを使用しているのでsmb.serviceの自動起動のタイミングでハマった。
thom.hateblo.jp

/mnt/encryptedのマウントが完了する前にsmb.serviceが自動起動してしまってsambaがエラーでフォルダアクセスできない。
簡易的な対処としてして自動起動ではなくrootユーザーのcrontabで起動させるようにした。

以下、smb.serviceの自動起動を無効化するコマンド。

sudo systemctl disable smb.service

以下はrootのcrontabに記述する内容。sudo suでrootになってからcrontab -eで編集した。

@reboot systemctl start smb.service

3. SE Linux

最近のLinuxではOSのファイル・フォルダーアクセス制御とは別にSE Linuxというセキュリティ強化機能が最初から導入され有効になっているケースが多い。
getenforceコマンドでステータスを確認でき、Enforcingと表示されたら有効になっている。
SE Linuxではどんなプロセスがどういうファイル・フォルダーにアクセス可能であるかをルール化しておくことができ、ルールに無いアクセスは却下される。

ルールに追記するのが本来のやり方だけど、フォルダーごとに手動でsamba_share_tタグをつけていく方法もある。(以下コマンド)

sudo chcon -t samba_share_t /mnt/encrypted/Archive

タグが付いたかどうかはls -Zコマンドで表示できる。

[thom@storage encrypted]$ ls -Z
unconfined_u:object_r:samba_share_t:s0 Archive
unconfined_u:object_r:samba_share_t:s0 Share

今回ハマった点としては暗号化処理で一時的にファイルの通り道となるsys_tmpフォルダーにsamba_share_tをつけ忘れたことで、sys_tmpで生成されたファイルを共有フォルダーに移してもWindows側から見えなくなったこと。

生成されたファイルは移動させる場合でも基本的には元親フォルダ―のタグを引き継いだままなのでSE Linuxによってsambaからのアクセスが拒否されているというのがWindowsで確認できない原因だった。

4. Linux Folder Access Control

注) Linux Folder Access Controlという名前は他の制御と比べて自分が分かりやすいようにそう呼んでるだけなので一般的な呼称でないことに注意。

ここでは曖昧な理解になりがちなファイルとフォルダーのアクセス権の関係性について説明しようと思う。
※一般的なAccess Controlの話(read/write/executeとowner/group/other)はLinux使ってたら耳タコなのであえて割愛。

特に分かりづらいのがとあるファイルやフォルダーが削除できるか・編集できるかという点である。

下図ではペンのアイコンに斜線が入ったものが書き込み不可に設定してあるとする。

上記の設定においてそれぞれのファイル・フォルダーに実際に行える操作は次のとおりである。

例えば、ファイルEは書き込み可能なのに削除できない、ファイルGは編集できないのに削除はできるというのは仕組みを知らないと直感に反しているように感じるかもしれない。原理としてはファイルやフォルダーの書き込み可否は、あくまでその中身についての話なので、そのファイル・フォルダー自体を消せるかどうかは常に親フォルダーが握っているということ。

Sambaの設定をする際にも特定フォルダーはrootにオーナーシップを持たせておいて中のフォルダー構成を勝手にいじれないようにしつつ、その子フォルダーにSambaによる書き込み権限を与えるといったやり方で制御することがあるのでOSアクセス権の基本は抑えておきたい。

5. Linux Firewall

最近のLinuxではファイアウォールポートが必要最小限のポート意外は閉じているようで、個別にオープンさせる必要がある。
Sambaを使うには445ポートが空いていればOK。

[thom@storage ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eno1
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 445/tcp
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

6. Network Firewall

ここは大手企業ならNW担当の領域なので特にサーバー管理で躓く場所ではないし、自宅やワンマンIT担当なら自分で設定してるはずなので原因の一つになりえるということを念頭に置きさえすれば、特に改めて説明することはない。
自宅のNW-FWはCisco CBS250の簡易ACLでネットワーク間のトラフィックを制御しているのみで、ポート単位での細かい制御はしてないので特に引っかかることは無かった。

7. Windows Firewall

自分から始めた通信に対する戻りのトラフィックはデフォルトで許可されているはずなので、特に追加設定してなければ引っかかることはないはず。

どこが悪いのかの切り分け

初期設定でうまくいかないときはサーバーにデータが入る前なので一時的にSE LinuxやLinux Firewallをストップして通信がうまくいくか確かめてみる。一旦ごっそり設定を解除してまずは通信を成功させ、それから通信ができなくなるまで一つずつ有効にしていき原因を探る。原因が分かったらきちんと調べて適切な設定をすることが重要。使えるからまるっと無効のままでいいやっていうのはセキュリティ的に非常にまずい。

その他

実際はデータ保管機能だけじゃなくて一時ファイルの自動削除スクリプトとか、永久アーカイブ対象ファイルを暗号化してAWSのS3バケットに保管する機能だったりを作っている。

AWS連携は以前書いた記事があるので詳しくは割愛。
thom.hateblo.jp

暗号化の仕組み等は別途書いてる記事がある。
thom.hateblo.jp

フォルダー構成は色々と悩んだ結果こうなった。アーカイブの分類とかもう少し凝った構成で計画をXにポストしてたけど結局アーカイブ本来の目的を考えると保管じゃなくて保存だから旧サーバー同様に分類しない投げ込み式を踏襲。

アーカイブ・暗号化・AWS連携・一時ファイルの自動削除を実現する実際のbashスクリプトは以下をcronで1分毎に動かしている。

#!/bin/bash
FILES="/mnt/encrypted/ToArchive/*"
TIMESTAMP=`date +'%Y%m%d%H%M%S'`
PASSWORD="非公開情報のため削除"

#file existence check for source folder 
if [ -n "$(ls -A /mnt/encrypted/ToArchive/)" ];then
  for f in $FILES
  do
    #duplicated file existence check for destination folder 
    if [ ! -e /mnt/encrypted/Archive/$(basename -- $f) ]; then
      gzip -c $f | openssl enc -e -aes-256-cbc -pbkdf2 -iter 99999 -salt -k $PASSWORD -out /mnt/encrypted/sys_tmp/$(basename -- $f).gz.aes
      encf=/mnt/encrypted/sys_tmp/$(basename -- $f).gz.aes
      hfname=/mnt/encrypted/sys_tmp/`sha256sum -- $encf | awk '{print $1}'`.gz.aes
      mv $encf $hfname
      /usr/local/bin/aws s3 cp $hfname s3://非公開情報のため削除/ --profile 非公開情報のため削除
      mv $hfname /mnt/encrypted/ToBeArchivedInMedia/
      mv $f /mnt/encrypted/Archive/
      echo $TIMESTAMP $(basename -- $f) $(basename -- $hfname) >> /mnt/encrypted/Archive/Index.txt
    else
      if [ ! -d /mnt/encrypted/ArchiveError/$TIMESTAMP ]; then
        mkdir /mnt/encrypted/ArchiveError/$TIMESTAMP
      fi
      mv $f /mnt/encrypted/ArchiveError/$TIMESTAMP
    fi
  done
else
  :
fi

find /mnt/encrypted/Temp/10_minutes -type f -amin +10 -exec rm {} \;
find /mnt/encrypted/Temp/24_hours -type f -atime +1 -exec rm {} \;
find /mnt/encrypted/Temp/30_days -type f -atime +30 -exec rm {} \;

前回のサーバーとしてもうひとつ進化した点はファイル名の匿名化が挙げられる。

これによって万が一AWS S3やメディアバックアップが流出しても、中身はもちろんそのタイトルすら読めないので他人には内容の類推すらできないという安全なものになった。

機能刷新でハマったところ

まず久々に触るのでBashが読めない。特に$(basename -- $f)の部分が、調べ直した先の参考サイトと記載違っており、なんで前回「--」を書いたのか、何の意味があるのか全く分からずに半日を費やした。

答えはこちらにあった。
zenn.dev

Linuxのコマンドは「コマンド 複数のオプション 引数」という構成になってて、「--」はここでオプション終わりですよと明示する書き方らしい。それが無いと例えば今回のケースだと$fに入ってくるファイル名にスペースが入ってた場合、そこで区切った前半の内容がオプションと一致するとまずい。。。。そんなことあるか?まぁ一応ダブルダッシュはいれとこう。


次に現行機種で動いている暗号化スクリプトをそのまま採用すると警告が出るのでハマった。
オプションに-pbkdf2 -iter 99999を追加したらエラーは解決したんだけど、なんで旧サバで入れてないんだ?と思ったらOSが古くてOpen SSLのバージョンがそのオプションが登場する前のものしかリポジトリになかったのが原因だった。

新旧暗号化オプションが混じると復号化の方法が分かれてしまうため、今回は新オプションで過去のアーカイブも暗号化しなおしてAWSにアップロードしなおした。どのみちファイル名匿名化でアップロードし直したかったのでちょうどよかった。

最後にどうしても分からなかったのが、共有フォルダー配下のフォルダーの削除操作を拒否する方法。
次のような不可解な現象に悩まされて海外掲示板等も読み漁ったけど解決していない。

実用上は特に困ってないのでひとまずはそのまま運用することにした。

おわり

おわり。

家庭内のデータを消失リスク・流出リスクで分類して対策を考える

今回は以下記事の続きというよりは前提となっている話。
thom.hateblo.jp

自宅のsambaサーバーが老朽化してリプレースしているという話を書いたが、この気にデータ保管のポリシーをしっかり立てて管理しようと思って整理してみた。

これまではsambaサーバーに組み込んだ機能ありきで適当に運用していたんだけど、今回はきちんとデータのリスクを考えて整理してみた。

まずデータのリスクを消失と流出の2つの軸で考えてテーブルを作る。

イメージしやすくするために、自分が持っているデータの消失リスク・流出リスクを例示してみた。

※思い出の写真などは、被写体によって変わる。モノや風景なら流出リスクは小、自分なら中、友人や家族なら大といったところか。

そして、それぞれのマスに対してどういう対応をとると良いかをポリシーとして整理してみた。

このあたりは考え方や技術的にとりうる対応が人によっても違ってくるのでもしこれを参考に同じようなことを考えたい方は自分が実現可能な範囲ですると良いと思う。場合によっては印刷という選択肢もあるかもしれない。

そしてそのポリシーを満たすような実際の解決策を考えていく。

実は今わざわざNASじゃなくてファイルサーバーを構築している理由としてはデータの取り扱いをシンプルにするためである。
セキュリティと利便性は基本的にはトレードオフの関係になることが多いが、利便性を損ねずにセキュリティを高められる解決策があるのならセキュリティが必要ないデータにも高いセキュリティを適用してしまえば良い。

ということで私が考えた解決策がこちら。

このように全データに対し、自分がとりうる最高レベルのセキュリティを統一的に適用することで流出リスクを無視して消失リスクだけでデータの保管方法を決めることができる。

ということで、次回こそこれをsambaでどうやって実現しているのかを記事にしようと思う。
と言ってもまだ構築途中なのでもう少し先になるかなと思う。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。