YAMAHA RTX1210 で作るゲストセグメント有り小規模ネットワーク

YAMAHA RTX1210 でちっちゃいネットワーク作る機会があったのでメモ。

論理構成は次の図の通り。

各セグメントの用途とセグメント間の接続要件は以下の通り。

  • 外部接続セグメント 10.0.0.0/24
    • インターネットに出て行くための上流セグメント。Untrustゾーン
  • サーバセグメント 10.10.0.0/24
    • DMZっぽいサーバ置き場。
    • アクセスセグメントからは全てのサーバと通信可能。
    • インターネット側(外部接続セグメント側)からの通信は Firewall で制限をかける。
  • アクセスセグメント 192.168.0.0/24
    • いわゆる内部セグメント。Trustゾーン
    • 外部接続セグメント・サーバセグメントには NAPT を介して制限無しで接続可能。
    • ゲストセグメントへの通信は不可。
  • ゲストセグメント 192.168.11.0/24
    • 訪問者にインターネット環境を提供する用&スマートフォンなどの私物接続用。Untrustゾーン
    • インターネットにだけ繋げればいい。
      • 外部接続セグメント(インターネット)には NAPT を介して制限無しで通信可能。
      • アクセスセグメントへの通信は不可。
      • サーバセグメントへの通信はインターネット側から接続する場合と同制限でなくてはならない。

物理構成は次の通り、 RTX1210 を中心として 4 セグメントが繋がる形になります。

外部接続セグメントとサーバセグメント間は上流の既設スイッチで接続済み、 Firewall 済み
なので、アクセスセグメントとゲストセグメント周りの通信制限が設定のキモになります。

まず、インタフェース周りの設定から。LAN2 と LAN3 には NAPT が入ります。
ゲストセグメントについては LAN1 に VLAN 11 を作り、そこに割り当てます。

# LAN1 アクセスセグメント
ip lan1 address 192.168.0.1/24

# LAN1 ゲストセグメント
switch control use lan1 on terminal=on
vlan lan1/1 802.1q vid=11 name=VLAN11
ip lan1/1 address 192.168.11.1/24

# LAN2 外部接続セグメント
ip lan2 address 10.0.0.2/24
ip lan2 nat descriptor 1

# LAN3 サーバセグメント
ip lan3 address 10.10.0.1/24
ip lan3 nat descriptor 2

# デフォルトゲートウェイ
ip route default gateway 10.0.0.1

# NAPT 設定。 LAN2 と LAN3 に出て行くパケットを NAPT する。
nat descriptor type 1 masquerade
nat descriptor address outer 1 10.0.0.2
nat descriptor type 2 masquerade
nat descriptor address outer 2 10.10.0.1
nat descriptor address inner 2 auto
nat descriptor masquerade incoming 2 reject

パケットフィルタではアクセスセグメント・ゲストセグメント間の通信制限と、ゲストセグメン
トから RTX1210 への接続制限を入れます。

# LAN1 アクセスセグメントフィルタ
# セグメント内通信を pass し、それ以外の 192.168.0.0/16 のパケットを reject すること
# でゲストセグメントからの通信を弾く設定。
ip lan1 secure filter in 103030 101102 101199
ip lan1 secure filter out 103030 101105 101199

# LAN1 ゲストセグメントフィルタ
# セグメント内通信を pass し、それ以外の 192.168.0.0/16 のパケットを reject すること
# でアクセスセグメントからの通信を弾く設定。RTX1210(192.168.11.1) へのSSH, Telnet, HTTP は弾く。
ip lan1/1 secure filter in 103110 103111 101102 101199
ip lan1/1 secure filter out 103111 101105 101199

# フィルタ
ip filter 101102 reject-nolog * 192.168.0.0/16 * * *
ip filter 101105 reject-nolog 192.168.0.0/16 * * * *
ip filter 101199 pass * * * * *
ip filter 103030 pass 192.168.0.0/24 192.168.0.0/24 * * *
ip filter 103110 reject-nolog * 192.168.11.1 tcp * 22,telnet,www
ip filter 103111 pass 192.168.11.0/24 192.168.11.0/24 * * *

以上の設定で、アクセスセグメントやゲストセグメントから外部接続セグメント・サーバセグメ
ントへの NAPT 通信、ゲストセグメントとアクセスセグメント間の通信遮断は実現できました。

ただ、ゲストセグメントからサーバセグメントに直接通信できてしまうため、パケット転送フィルター
を設定することで、ゲストセグメントからサーバセグメントに向かう通信は、外部接続セグメン
トに転送するようにしてやります。
これにより、ゲストセグメントからサーバセグメントに向かう通信は一旦外部接続セグメントを
介するので、既設 L3 スイッチでの Firewall が適用されることになります。
(RTX 1210 でフィルタしようとすると、設定箇所が散らばるので管理負荷が上がります)

# パケット転送フィルターに与える条件(ゲストセグメントからサーバセグメントに向かう通信)
ip filter 200000 pass 192.168.11.0/24 10.10.0.0/24 * * *

# パケット転送フィルター
# ゲストセグメントからサーバセグメントへの通信は外部接続セグメントに転送する
ip forward filter 11 1 gateway 10.0.0.1 filter 200000

# ゲストセグメントにパケット転送フィルターを設定する
ip lan1/1 forward filter 11

以上で、ゲストセグメントからサーバセグメントに向かう通信は外部接続セグメントを介する
ようになるので、通常のインターネット側から通信する場合と同様、フィルタがかかることに
なります。
フィルタ型ルーティングでもできそうだけど未検証)

めでたしめでたし。

Schedule Watcher Ver5.62 に祝日データ(山の日)を追加する

Schedule Watcher Ver5.62.160514 に2016年から追加されてた祝日 8/11 山の日を追加する方法。

Holiday.dat に

 8112016    000山の日

を追記する。
海の日の後あたりがいいでしょう。
固定長フォーマットなので先頭や途中の半角スペースを省略しないように。

追記した後、Schedule Watcher を再起動して2016年以降に祝日が反映されていれば完了です。

Holiday.dat はメニューの設定→環境設定で開くダイアログの「データフォルダ」タブの
「スケジュールファイル」に書いてあるフォルダ・ディレクトリにあります。
Windows の一般的な形式(文字コードSJIS、改行コードは CRLF)なのでメモ帳などでも弄
れると思います。



Schedule Watcher には 10年以上お世話になってるので課金しようそうしよう。

※迷惑かかるとまずいのでお断り。中の人はSchedule Watcher作者のSAKO氏と無関係な第三者です。

Java (JCE) で AES 暗号化するときの PKCS#5 の実態は PKCS#7 なのか?

結論

JCE (Java Cryptography Extension) の AES/CBC/PKCS5Padding のパディングは、実際には PKCS#7 でパディングしている。
(少なくとも Oracle Java8_141 環境下では)

経緯

Java で AES 暗号化を扱う機会があり、ググっていたところ AES/CBC/PKCS5Padding がデフォルトサポートで使いよい。というところまで行ったところで、
「AES ってブロック長 128bit(16byte) だから 8byte までしかパディングできない PKCS#5 だとパディングできないんじゃ?」
と疑問に思ったわけです。

PKCS#7 であれば 16byte ブロックでも問題なくパディングできるので、本来なら AES では PKCS7Padding であるべきなのにデフォルトサポートはしていない。
PKCS#7 は PKCS#5 のスーパーセットなので、JCE の PKCS5Padding が実際には PKCS#7 でパディングしているなら「名が体を表していないだけ」ということになる。

そこらへんを書いた話はないものかと、java pkcs5 pksc7 とかでググっても「PKCS#5と#7は同じ」とか「互換性がある」とかで残念ながらはっきりしたことはわからなかった。

Java 同士でやりとりする分にはいいけど、言語を跨いでやりとりするときに、ここらがはっきりしていないとトラブルよなぁ…。。

ということで、 JCE の PKCS5Padding は PKCS#7 の動作をしているのかどうかというところを検証してみた。

検証

以下の環境で検証を実施。

C:\Windows\System32>java -version
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.141-b15, mixed mode)
検証コード

次の 2 パターンでの暗号化結果を比較し、等しければ OK。

  • JCE の PKCS5 パディングで暗号化した場合 (AES/CBC/PKCS5Padding)
  • 自前で PKCS7 パディングしたバイト列を暗号化した場合 (AES/CBC/NoPadding)

平文長(元データ長)は 1 〜 16 byte として、それぞれで比較する。

import java.security.Key;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESPaddingTest {
    public static void main(String[] args) {
        try {
            // 元データ長が 1 〜 15 の場合
            for (int i = 1; i < 15; i++) {
                // 元データ
                byte[] base_sequence = new byte[i];
                // 自前パディングデータ
                byte[] padded_sequence = new byte[16];

                // PKCS7 で自前パディング
                byte pad = (byte) (padded_sequence.length - i);
                for (int j = i; j < padded_sequence.length; j++) {
                    padded_sequence[j] = pad;
                }

                boolean result = compare(base_sequence, padded_sequence);
                System.out.printf("[Source length %2d] %s%n", i, (result ? "OK (Same result)" : "Fail (Some difference"));
            }

            // 元データ長が 16 の場合(16byte時だけ分離してるのがちとダサい)
            byte[] base_sequence = new byte[16];
            byte[] padded_sequence = new byte[32];
            // PKCS7 で自前パディング
            for (int j = 16; j < padded_sequence.length; j++) {
                padded_sequence[j] = 16;
            }
            boolean result = compare(base_sequence, padded_sequence);
            System.out.printf("[Source length %2d] %s%n", 16, (result ? "OK (Same result)" : "Fail (Some difference"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 未パディングのバイト列と自前パディングのバイト列の暗号化後の結果が等しいかチェックする。
     * @param base_sequence 未パディングのバイト列
     * @param self_padded_sequence 自前パディングのバイト列
     * @return true 等しい。false 差異あり。
     * @throws Exception 
     */
    private static boolean compare(byte[] base_sequence, byte[] self_padded_sequence) throws Exception {
        byte[] key_raw = new byte[16];  // all 0
        byte[] iv_raw = new byte[16];   // all 0

        Key key = new SecretKeySpec(key_raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(iv_raw);

        // Oracle JCE Provider で PKCS5Padding を指定した場合
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
        byte[] base_enc = cipher.doFinal(base_sequence);

        // 自前パディングした場合(パディング済みなのでNoPadding)
        cipher = Cipher.getInstance("AES/CBC/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
        byte[] padded_enc = cipher.doFinal(self_padded_sequence);

        return Arrays.equals(base_enc, padded_enc);
    }
}

※上のコードは NYSL Version 0.9982 扱いです。

検証結果

暗号化されたバイト列を比較した結果、以下の通り全部同じだったので、JCEPKCS#5 パディングは実際には PKCS#7 パディングでした。ということに。

[Source length  1] OK (Same result)
[Source length  2] OK (Same result)
[Source length  3] OK (Same result)
[Source length  4] OK (Same result)
[Source length  5] OK (Same result)
[Source length  6] OK (Same result)
[Source length  7] OK (Same result)
[Source length  8] OK (Same result)
[Source length  9] OK (Same result)
[Source length 10] OK (Same result)
[Source length 11] OK (Same result)
[Source length 12] OK (Same result)
[Source length 13] OK (Same result)
[Source length 14] OK (Same result)
[Source length 16] OK (Same result)

暑くなってきたしメントールスプレーでも作ろうか

本題

ハッカ油じゃなくて純正スースー成分のメントールでスプレー作ろう。
ハッカ油スプレー作ってたけど、猫の都合で念のため素材変更ですよと。

用意するもの

  • 原材料
    • メントールクリスタル(量があるので1夏2夏分は余裕かと)

    • 無水or消毒用アルコール(水にこだわりたい人は無水で)

    • 水(水道水でも蒸留水でもお好みで)
  • 道具
    • きれいなメモ用紙 or 薬包紙
    • 丈夫なスプーン or 乳鉢
    • スプレーボトル(20ml程度. アルコールを入れるのでガラスかポリエチレンかポリプロピレン製がおすすめ. 写真はコー○ンで売っていた20ml品)


作り方

  • メモ用紙上に適量のメントール結晶を取り出します。写真では1本ですが出来上がり量20mlに対して6本ぐらいが目安です。一度適当に作ってみて、効きが弱ければ次から増やす。効きが強ければ減らすで自分好みに調整していきましょう。

  • メモ用紙を半分に折りメントール結晶を挟みます。その上からスプーンの腹でメリメリ押しつぶし、結晶を粉末にしてしまいます。(これをやらないとなかなか溶けないので)

  • スプレーボトルに入れます。ボトルが濡れてると粉末メントールがボトルの口に貼り付くので用心しながら入れましょう。

  • アルコールをスプレーボトルの半分(無水の場合)〜3/4あたり(消毒用の場合)まで入れます。

  • ボトルの首の部分をつまみ、底が円を描くようゆっくりと回しながら溶かします(試験管で試薬を溶かすように:中学の理科の教科書参照)。ときどき光に透かしてみて、固体分がなくなっていればOK。
  • 十分に溶けて混ざったら、水を入れて量を調整します。

  • 出来上がり。あとは腕にかけるなり腹にかけるなりご随意に。メントールクリスタルは沢山あるからいっぱい使っても安心。


メントールスプレー一式あふぃりんく

なぜクレジットカード払いを使わないのか? → 主に管理が手間だから

カードを持ってるのに現金払いを好んで使う30代の友人に、その理由を聞いてみた。『なぜクレジットカード払いを使わないのか?』 - クレジットカードの読みもの
を読んでの感想文。


よく言われるクレジットカード払いのメリットは

  • 現金の支払いは基本的に後になればなるほど額面でお得(利息がつく場合)
  • 支払が手早い(現金払い比。ICカードには負ける模様)
  • ポイントが付く
  • 手元に現金が無いときに助かる場合がある
  • 海外に行くとき
    • 現金を外貨に両替して持っていくより安全
    • 外貨両替より現地でキャッシングしたほうが為替レートがマシな場合がある(利息付く前に即返済が前提) → 楽天カード海外キャッシングの実例

これに対して、クレジットカード払いのデメリットを挙げると

  • セキュリティ懸念
    • 購入情報がカード会社に集約されるので、何かあったときに面倒なことになりそう(漏洩や司法当局の照会)
    • 不正利用が不安
  • 管理コストが増える
    • 現金が減るタイミングのズレ
    • 不正利用対策に明細を確認しろというが明細が増えると突合の手間がばかにならない
  • その他
    • サインレス増えてるとはいえサインやPIN入力が面倒
    • 支払先にかかる手数料が気になる
    • 現金なら手元分が上限だけど、カード払いにはそれがないからついつい使い込みそう
    • ポイント貯まるとはいえ使途が限定されていて使い物にならなかったり有効期限があったり確認が面倒(カードによる)

こんなものだろうか。

個人的には管理コストとセキュリティ懸念(主に購買情報が掌握される危険性)、加えて個人
の小規模店舗だと手数料の負担が心苦しい。


管理コストについては、やはり現金が必要となるタイミングが遅れるのが手間かなと。
(これはクレジットカードのメリットでもあるわけだが)

現金だと「現時点」に注目するだけで済む=忘れても OK なわけだけど、クレジットカード
払いでは未払い金が生じるので、実際に引き落とされるまで現金の出入りの見通しを立てて
引き落とし日に残高不足にならないようにしておかないと、うっかり引き落とし不能とかで
信用情報、いわゆるクレヒスに傷が入ってしまう。

本来、クレジットカードはここらの残高不安がない安定した資産と収入がある身分の人を対
象としたものなんだろうけど…
(だからこそカードには信用調査があるわけなんだけど、昨今はリボ払い誘導とか結構な情弱ビジネス臭もする)


これに加えて、明細確認の手間。

ブコメでも指摘があったように、カードの利用頻度が増えると明細も増える→利用実績
(自分の記憶やカード利用時のレシート)との突合が大変に面倒になる。

Amazonkindle、お前のことだ!
セールの時にあれもこれもと買うと、カードの明細に同じ日付の「AMAZON DOWNLOADS」が
ずらり並んでぶ。
購入IDとか載らないので、購入時のメールと&金額で突合するしか手が無く、コミックを
あれやこれやと手を出してると金額まで同じとかで大変に手間。
一般商品と同じくカートに入れて一括決済できるようにしてくれ、 Amazon よ。

閑話休題、「不正利用を防ぐためには明細確認が必須」とは言われているものの、例に挙げ
たようにここの突合が相当にコスト(記憶負担とかレシート保管&管理の手間とか)かかる
から辛いよねと。
現状のシステムだと、面倒だから確認しなくなって→不正利用だ、危険、怖い。となってし
まうのはだと致し方ないように思える。


コンビニとかの細々とした支払にも使っていると結構な手間だと思うのですが、世間の皆様
はどうやって管理してるんでしょうか。

自分は カードで支払う → Excel に未払い金として記録しておく → オンライン明細に上がっ
て来たと突合する → 引き落としが終わったものは削除する としてるものの、月10回未満
程度でも結構な手間でして。

店によってはカードの利用実績が上がるタイミングがずれてたりして、先月使ったはずなのに
明細に上がってこなくて、翌月に上がってきたり……とかあるし。


だれか、現金、ICカード残高、口座残高、カード利用状況突合をひっくるめて面倒見られる
いかした家計簿Excelくださいorz http://b.hatena.ne.jp/entry/300974916/comment/sgo2


マネーフォワードはね、ログイン情報渡してスクレイピングというのがイヤ。
住信SBIのようにカード各社が OAuth とか使った参照系 API を提供して、それを叩くのならまだ許せるんだけど。。
あと、結局明細が更新されるまで待たないといけないことに違いはないので、現状が即時反映さ
れないのは同じ。


デビットと電子マネーICカードでの支払いはどうだろうと考えると、

デビットは即時に残高減るから時間のズレの問題は消えるものの、上限額=預金額という天井の高さがネック。
チャージという形で任意に天井を設定できるチャージ式ICカードは悪くないけれど、、

双方とも、微妙に使い勝手が悪いのはカード内の残高を把握しにくい点。

ICカード単体型だとカードリーダーなりの端末がないと確認できないわけで、ふとしたときや
レジ待ち中に残高あったっけ?と、現金なら財布を覗けば終わることができない。

スマートフォン一体型だとその辺カバーされるんだろうけど、アプリ操作が必要なのでちょっと
手間なような気がする(使ったことないので何とも)。
あと、携帯持ち歩かないといけないという点(携帯の意義否定())

ICカード電子ペーパー付いてて都度残高表示が変わったりすればベターかな。
とはいえ、ICカードのIDによる利用者行動の追跡懸念は残るのでなんとかならんものかと…。


ここらが解消されて、取り扱いコストが利用者店舗側とも現金のそれよりに安くなる電子決済
システムができれば現金払いだと逆に手数料かかるみたいになって、がらりと風景変わるだろ
うけどねぇ。
ついでに、支払と同時にレシート,領収書がカードに記録されて後から電子的に参照可能なので
お願いしゃす。


最後に、利用状況を管理しないといけないようなビンボー人はカード使うなって言うならば、
そういうビンボー人にはカードを発行するべきじゃないし、そうなったビンボー人が現金払
いするのは見逃してね。それしか支払う術がないんだもの。
そしてクレジットカードは、その仕組み上、現金が常時潤沢で余裕のある人・店舗が使うこ
とが前提になってるので、そこから外れた日々カツカツで現金回してる人らには向かない決
済方法と。

XBee 送信ステータス 0x26 の意味

XBee でブロードキャスト送信していると、その送信ステータスで 0x26 が返ることがあるんですよ。

公式リファレンス によると、

0x26 = Broadcast source failed to hear a neighbor relay the message

ということで、ご近所がリレーしたメッセージが聞こえなかった(直訳)ということらしい。

ZigBee のブロードキャスト送信がどうなっているのかというと、知らないブロードキャストメッセージを受信したら再送信。という仕組みになっているらしい(Zigbee Network Layer Tutorial - Part 3: Broadcasts and Neighbors)。

したがって、「ブロードキャストメッセージを投げたものの、ご近所が再送信するはずメッセージが聞こえなかった。何かおかしい!」と言う意味になります。

試しに、コーディネータだけ動かしておいて、ブロードキャスト送信すると、周りに再送信するノードが誰もいないので、送信後 1 秒ほどで 0x26 が返ってきます。
それに対して、ルータが 1 台でもいると、 0x00 が返ります。

つまりは ぼっち、寂しいよね。

XBeeの通信チャンネルの指定の仕方

2016/9/12 修正 当初 S2C で ch 26 が使えないとしてましたが対応しているようです。
元記事

XBee ついでなので、XBee ZB S2C が使う通信チャンネルの指定の仕方。

直感的には AT CH コマンドがあるから、これで指定できそうに見えるのだけれども、AT CH は無慈悲にも「read-only」。
どうすんだよ!と言うと、コーディネータで AT SC コマンドを使い、スキャンするチャンネル=選択可能なチャンネルを制限してしまう。
例えばチャンネル12を使いたい場合は SC に 0x0002 を与えて、そこしか選べないようにする。

ch11 0x0001
ch12 0x0002
ch13 0x0004
ch14 0x0008
...
ch25 0x4000
ch26 0x8000

という感じ。
チャネル26相当の 0x8000 も設定できてしまうけれど、XBee ZB S2C はチャンネル26に対応していないから通信できなくなる。(2016/9/12 修正)

また、ルータとエンドデバイスでは、この方法でチャンネル指定しないほうがよい。
ルータとエンドデバイスは、スタートアップ時にコーディネータにぶら下がる形になっているので、どのみちコーディネータが使っているチャネルになるし、コーディネータのチャンネルと違うチャンネルに制限してしまうとjoinできなくなってしまう。