dorapon2000’s diary

忘備録的な。セキュリティとかネットワークすきです。

Uniqys kitハンズオン#1に参加した

表題のハンズオンでやった内容と感想を書いていきます。


mobilefactory.connpass.com

こちらのイベントに参加しました。

Uniqys Kitは、UniqysProjectの一環で開発されているDApps開発サポートツールです。

公式サイト:https://uniqys.net/ja

ということで、今話題のブロックチェーンを使ったアプリを簡単に作れちゃう開発者向けのツールのハンズオンですね。ブロックチェーンと言うと仮想通貨を思い浮かべますが、仮想通貨はあくまでブロックチェーンを使った応用例の1つで、アプリケーション(= DApps)も作れます。逆に言うと、仮想通貨の分野ですらこれだけ可能性を見出してるのですから、更に広い分野でも期待されています。

ただ、自分はどのようにしてDappsが出来上がるのか全く知らない中でのハンズオンだったので、Uniqys Kit頼む!俺の代わりに頑張ってくれ!という気持ちでした。結果から言うと、Uniqys Kitは本当に頑張ってくれて、ほとんど意識することなく初めてのDAppsを作ることができました。


Step 1 | Uniqys Kit Simple Samples

ハンズオンの内容は上のリンクにあります。作成したアプリは、ブロックチェーン上でお寿司の売買ができるアプリです。

f:id:dorapon2000:20190519013245p:plain

「にぎる」と通貨「ガリ」を使ってお寿司を作れるのですが、その際にアラートで署名するかどうか確認が取られます。

f:id:dorapon2000:20190519013248p:plain

注意として、Node.jsをv10系へ、pythonを2.7系へバージョンの変更をしておくことです。会場でもここらへんでトラブルが発生しているようでした。自分はパッケージマネージャでどちらも切り替えました。また、内容がMac/Linux向けにかかれているようで、Windowsの方は謎のエラーと戦わなくていけないかもしれません。

さてハンズオンですが、想定のMacでバージョンも予め変えておいたおかげか、運が良かったか、特に大きなエラーに見舞われることなくアプリを作れました。中ではnode.jsとvue.jsが使われています。node.jsは昔触ったことがありましたが、vue.jsはなかったので、会場につくまでの電車の中でちょろっと使い方を眺めた程度でしたが、なんとかなりました。おそらくどちらに触れたことがなくても、HTML/CSS/jsのいろはさえわかれば、なんとかなると思います。

ハンズオンの最後に追加課題があって、時間に余裕があったのでチャレンジしました。1つ目のお寿司の追加順序を前からにするのは、お寿司リストをreverse()しただけです。2つ目以降はjsに慣れていないこともあり時間内にできませんでした。

自分が書いたコードはgithubにあげておきます。

github.com

その後の懇親会でお寿司とピザが出ました。

こういう機会がないとなかなか踏み出せないので、とてもいい経験になりました。

複数ファイルのデータをまとめて1枚のヒストグラムにする (gnuplot)

同じ条件で試行した実験データが100個別々のファイルであるとして、全てを1つのヒストグラム上でまとめます。第一段階として、100ファイルを1つのファイルに連結します。第二段階として、そのファイルをgnuplotで読み込んでヒストグラムにします。

データをまとめる

シェルでちゃっとやりました。catに複数ファイルを指定することでファイルを連結できます。

$ find . -type f | grep sojourn.tr | xargs cat > all_sojourn.tr

ヒストグラム

set xlabel "sojourn time (ms)"
set ylabel "numebers"
binwidth = 10
bin(val) = binwidth * floor(val/binwidth)
plot "all_sojourn.tr" using (bin($2)):(1.0) smooth frequency with boxes lw 2 title "sojourn histogram"

f:id:dorapon2000:20190422123145p:plain

3行目〜5行目は、gnuplot公式のマニュアルに書かれていたヒストグラムのグラフ出力方法を、少し変えたものです。 特に調べてないので式の雰囲気しかわかりませんが、binwidthにヒストグラムのグラフの刻み幅を指定できます。 using 〇〇:△△ smooth frequencyヒストグラムにします。 〇〇が同じものについて、△△の合計値が出力されるようで、ヒストグラムにしたいので△△には1を指定します。 $2は2列目の値のヒストグラムを取るという意味。

with boxes以下は参考サイトを参考にして、適当につけたオプションです。 with boxesがグラフをデフォルトの折れ線グラフから棒グラフに変えます。 lw 2がlinewidthを指定していて、デフォルトより少し太めになります。 title "sojourn histogram"はタイトルです。

参考

http://www.gnuplot.info/docs_5.0/gnuplot.pdf#page=90

Gnuplotで相対頻度分布を描く - Qiita

gnuplotでヒストグラムを描く - メモログ(雑記)

Path MTU Discovery

Path MTU DiscoveryのIPv4IPv6のどちらの視点でもまとめました。

Path MTU Discovery

インターフェースごとのMTUの違いを解決する方法として、(1) ルータ上でのフラグメンテーションと、(2) 送信元でのフラグメンテーションの2種類の方法があります[1]。IPv4ではDFフラグのon/offで両方でき、IPv6では仕様により後者の方法しかとれません。

(1) IPv4はルータ上で次のリンクのMTUがパケットサイズよりも小さければ、パケットを分割します。

(2) 適当なMTU値で送り、ICMPメッセージが返ってきた場合、そのMTU値に分割して再送します。ICMPv4の場合type 3, code 4「Fragmentation Needed」、 ICMPv6の場合はtype2, code 0「Packet too Big」

フラグメンテーションの問題

3つあります。

フラグメンテーションされたパケットをさらに分割してしまうと、受信側でオリジナルのフラグメントなのかサブフラグメントなのか区別がつきません。

また、最初のフラグメントが届いてからメモリ内にフラグメントを保持しておく時間をressembly timerと呼び、1つでもフラグメントが届かずタイムアウトすると、それまで受信したすべてのフラグメントを破棄してしまいます。

PMTUDの問題

PMTUDブラックホールという問題が知られてます[3] 。これは、ICMPメッセージが経路上のルータやFW等で破棄されてしまい、送信元にフラグメンテーションせよというメッセージが返ってこない問題です。もし、経路中にブラックホールがあるようであれば、送信側でMTU/MSS値を予め設定することになりそうです[4] [5]。ネットワーク側の解決策としてフラグメントに関するICMPメッセージを通したり、DFフラグを0にして無理やり分割してしまう必要があります[6] [7]。

手元でチェック

以下の2点について気になったので手元で簡単にチェックしてみました。

  • IPv4でDFフラグが1のパケットの割合
  • IPv6でフラグメント拡張ヘッダを含むパケットの割合

まずDFフラグついて。適当なサイトを10個以上開いたりメールチェックなどをしてトラフィックを発生させ、Wiresharkで通信を見てみます。キャプチャしたIPv4パケット32780個のうち、79.4%がDFフラグつきで、残り19.6%がDFなしでした。基本はDFフラグがついているようですが、何にDFフラグがついていないのかはよくわかりませんね。一応、それぞれのトラフィックの内約とパケット長の分布の図を貼っておきます。

f:id:dorapon2000:20190418221617p:plain
[DF=1] トラフィックの内約
f:id:dorapon2000:20190418221715p:plain
[DF=1] パケット長の分布
f:id:dorapon2000:20190418221747p:plain
[DF=0] トラフィックの内約
f:id:dorapon2000:20190418221815p:plain
[DF=0] パケット長の分布

次にフラグメンテーション拡張ヘッダについて。トラフィックの生成方法は先程と同じです。しかし、キャプチャしたIPv6パケット7602個のうち、フラグメント拡張ヘッダが含まれるものは1つもありませんでした。つまり、フラグメンテーションされていません。あれ?という気持ちです。どうやら、ICMPメッセージを受け取ったとき、IPのフラグメンテーション機能ではなく、TCPのMSSで管理をしてしまうのが望ましいとのことです[9] [12]。ちょうど現在IPv6のPMTUDが盛んに議論されているようでした[13]。ちなみに、IPv4でキャプチャしたほうでもMFフラグが立っているものを調べると0個でした。調べていませんが、おそらくこちらも同じような理由なのかもしれません。

IPv6拡張ヘッダのセキュリティ

別の問題として、そもそもIPv6の拡張ヘッダがあった場合、セキュリティとコストの兼ね合いから破棄してしまうルータも現実にはあるようです[8]。フラグメントヘッダのセキュリティについては、RFC7112[10]で言及されています。パケットを分割する際に、L4ヘッダは先頭フラグメントにしか付属しないため、FWがそれ以外のフラグメントをフィルタリングしたいときにL4情報を使えないという問題があります。望ましないフラグメントは禁止すべきとしています。

実際のインターネットでどれほど破棄されてしまうかはRFC7872[11]にあります。データは2015年のもので、フラグメント拡張ヘッダを付けて、Webサーバとの通信で28.26%が、メールサーバとの通信で35.68%が、ネームサーバとの通信で55.23%が、経路途中で破棄されてしまうようです。%には同じASで破棄されたものも含まれています。また、文献[8]でもDNSゾルバの37%がIPv6のフラグメントを破棄したとあります。

もっと広く使われているものだと思ってました。厳しいですね汗。

References

[1] Russ White, Ethan Banks, "COMPUTER NETWORKING PRBLEMS AND SOLUTIONS", pp.140-142, 2018

[2] Douglas E. Comer, "Comuter Networks and Internets SIXTH EDITON", pp.415-420, 2015

[3] K. Lahey, "TCP Problems with Path MTU Discovery", RFC2923 ,2000

[4] IPv6 Path MTU Discovery にどっぷりとハマる。 » かけまわる子犬。

[5] IPv6 の MTU | あたがわの日記

[6] IPv6 PMTU Discovery Blackholeの盲点

[7] Path MTU Discoveryとは - その2

[8] Dealing with IPv6 fragmentation in the DNS | APNIC Blog

[9] Fragmenting IPv6 | APNIC Blog

[10] F. Gont, V. Manral, R. Bonica, "Implications of Oversized IPv6 Header Chains", RFC7112, 2014

[11] F. Gont, J. Linkova, T. Chown, W. Liu, "Observations on the Dropping of Packets with IPv6 Extension Headers in the Real World", RFC7872, 2016

[12] J. McCann, S. Deering, J. Mogul, R. Hinden, Ed., "Path MTU Discovery for IP version 6", RFC8021, 2017

[13] IPv6 Summit in Tokyo 2018 IPv6標準化最新状況

macの「ディスクがほとんど一杯です」通知を消す方法 (消せない)

macの「ディスクがほとんど一杯です」通知は消しても数分するとまた表示されて本当に邪魔です。こっちは少ない容量を一生懸命やりくりしているんだと突っ込みたくなります。通知を消す方法をグーグル先生に聞いても、ディスクの整頓術ばっかりで肝心の通知を切る方法がありません。

英語で調べたら数年の悩みが一瞬で片付いたので共有します。

f:id:dorapon2000:20181216121307p:plain


環境

通知を消す方法

apple.stackexchange.com

$ launchctl unload -w /System/Library/LaunchAgents/com.apple.diskspaced.plist

ターミナル上でこれ打つだけです。こんなことに悩まされていたとは、、、

デフォルトだと20GBより容量が少なくなったときに通知が出るみたいで、その数を変えることもできます。

$ defaults write com.apple.diskspaced minFreeSpace 1

自分はこっちの方法で1GBにしました。再起動すれば反映されます


追記

www.reddit.com

The minFreeSpace option and many others appear to have been removed recently, for no reason.

MojaveだとminFreeSpaceというオプションが使えなくなったようでした。

通知を表示させなくする方も試したのですが、これも上で言及されているエラーが出てしまいました。

$ launchctl unload -w /System/Library/LaunchAgents/com.apple.diskspaced.plist
/System/Library/LaunchAgents/com.apple.diskspaced.plist: Operation not permitted while System Integrity Protection is engaged

他のサイトの方法でも通知消えず。

apple.stackexchange.com

$ defaults write com.apple.diskspaced removeAllNotifications -bool true
$ killall diskspaced

tutel.me

$ defaults write com.apple.diskspaced freeSpaceWarningLevel 1
$ defaults write com.apple.diskspaced warningInterval 36000000
$ launchctl stop com.apple.diskspaced && launchctl start com.apple.diskspaced

# 設定した値がロードできてません
$ grep -A6 debugLog <(strings $(find /System/Library/PrivateFrameworks -name diskspaced -print -quit))
debugLog (BOOL) - log additional debug information. Default: NO
Commands:
removeAllNotifications - Removes all scheduled and delivered user notificiations.
removeAllNotifications
com.apple.diskspaced
_mbsetupuser
Ignoring low disk notification during migration.
--
debugLog
systemUpdateDate
com.apple.updatesettings
Interval since system update :%f
alloc
init
lowSpaceTimer

これらもMojaveのときに消えてしまったんでしょうか汗

$ grep com.apple.diskspaced /var/log/system.log
Dec 16 15:32:08 dorapon-MBA com.apple.xpc.launchd[1] (com.apple.xpc.launchd.domain.user.501): Service "com.apple.xpc.launchd.unmanaged.diskspaced.2257" tried to register for endpoint "com.apple.diskspaced" already registered by owner: com.apple.diskspaced

ログにはすでに登録されている旨が書かれてますね。

只今模索中


追記2

検索しても皆さん解決策がなくて困ってるようですね汗。今後改善して、設定で消せるようになることを期待します。

参考

BoostNoteからMarkdownを抽出する

タイトルのとおりです。 最近Typoraというマークダウンエディタを発見しまして、非常に使い勝手がいいので、今まで使っていたBoostNoteからそちらに移行しました。 その際に、BoosteNoteのデータを全部マークダウンとしてエクスポートしたいのですが、1個づつでしかできません。 本来BoostNoteからしかデータへはアクセスできず、ディスク上に保存されるファイルは乱数のような名前です。 中身もマークダウンではなくcsonと呼ばれるJSONCoffeeScriptが合体したようなデータでした。

ということで、マークダウンを抽出するスクリプトを書きました。


使い方

コードgithub上に置いてありますのでcloneしていただくか、コピペして依存モジュールを手動でインストールしてください。

git clone git@github.com:dorapon2000/boostnote2markdown.git
pip install -r requirements.txt
python boostnote_to_markdown.py

フォルダ選択のダイアログが開くので、BoostNoteのワーキングディレクトリを指定してください。ワーキングディレクトリ内にmarkdownというディレクトリができて、その中にフォルダ構造を維持したままマークダウンがエクスポートできています。

コード

github.com

github上にコードがあります。

BoostNoteは./boostenote.jsonにフォルダ情報、./notes/*.csonにノートが保存されています。*.csonには親フォルダ名とデータがcson形式で保存されています。初めて聞いた形式だったのですが、以下のサイトに簡単な説明があります。

blog.kazu69.net

csonを読むモジュールはないかなと探したら、pycsonというドンピシャなものがあったのでこちらで読み取りました。使い方もjsonモジュールとほぼ同じで助かりました。

*.csonからデータ部分だけ取り出したら、BoostNote上のフォルダ構造を再現しながらマークダウンファイルに変換するだけです。 *.csonにかかれている親フォルダ情報(088f99dbeb2ee050cc8bみたいな)は記号なので、boostenote.jsonから記号に対応するフォルダ名を取得します。

注意点

作成するマークダウンの名前はBoostNote上のタイトルとなりますが、特殊記号が使われている場合適当な文字に変換しています。

特殊文字というのは「 \/:,*?<>|」で、Windowsでファイル名に使えないものです。 私の場合、論文名をそのままタイトルにしたり日付を入れたものがあるので、「:」や「/」が引っかかりました。 記号は[colon]や[slash]というふうに置換して、とりあえずマークダウンは作成してもらうようにしています。 削除するなり適宜あとで直してください。

import os
import re
import json
import cson
import tkinter
import tkinter.filedialog


def convert_to_name(dir_key, conf):
    """Convert from directory key  to directory name
    :param  str dir_key:    key in boostnote.json/folders/key
    :param  dict    conf:   dictionary converted from boostnote.json
    :rtype: str
    :return: directory name
    """

    return [meta['name'] for meta in conf['folders'] if meta['key'] == dir_key]


def sanitize(str_):
    """Sanitize string for Windows
    target: \\/:,*?<>|
    :param  str str_:   string you want to sanitize
    :rtype: string
    :return:    sanitized string
    """

    if re.search('[\\/:,*?<>|]', str_) is None:
        return str_

    str_ = str_.replace('\\', '[backslash]')
    str_ = str_.replace('/', '[spash]')
    str_ = str_.replace(':', '[colon]')
    str_ = str_.replace(',', '[hyphen]')
    str_ = str_.replace('*', '[star]')
    str_ = str_.replace('?', '[question]')
    str_ = str_.replace('<', '[less]')
    str_ = str_.replace('>', '[greater]')

    print(f'"{str_}" is sanitized')

    return str_


def extract_md_from_BoostNote():
    """Extract Markdown from BoostNote
    """

    cnt_success = 0
    cnt_skip = 0

    root = tkinter.Tk()
    root.withdraw()
    msg = 'Select your BoostNote working directory'
    boostnote = tkinter.filedialog.askdirectory(title=msg)
    conf_json = os.path.join(boostnote, 'boostnote.json')
    with open(conf_json) as f:
        conf = json.load(f)

    notes = os.path.join(boostnote, 'notes')
    for file in os.listdir(notes):
        with open(os.path.join(notes, file)) as f:
            note = cson.load(f)

            if note['type'] != 'MARKDOWN_NOTE':
                cnt_skip += 1
                continue

            key = note['folder']
            folder = convert_to_name(key, conf)
            title = note['title']
            content = note['content']

            if note['isTrashed']:
                folder = 'Trash'

        folder = sanitize(folder)
        title = sanitize(title)

        output_dir = os.path.join(boostnote, 'markdown', folder)
        os.makedirs(output_dir, exist_ok=True)
        output_file_name = title + '.md'
        output_file = os.path.join(output_dir, output_file_name)

        with open(output_file, 'w') as f:
            f.write(content)

        cnt_success += 1

    print('=============================================')
    print('Converting BoostNote to Markdown is Success!!')
    print(f'success: \t{cnt_success}')
    print(f'skip:    \t{cnt_skip}')


if __name__ == '__main__':
    extract_md_from_BoostNote()

Ubuntu 16.04でsudoとsuができなくなった問題

ubuntuをスリープから起こしたら、ターミナルの色のついた文字だけが表示されていない状態でした。 ターミナル再起動してもシェルを変えても治らないので、PCを再起動して直したんですが、そしたら今後はsudoが使えないという...

Ubuntuはデフォルトでsuが使えないようなので、管理者権限で実行する手段がなくなります。

環境

  • Ubuntu16.04

事象

$ sudo ls
[sudo] dorapon のパスワード:
dorapon は sudoers ファイル内にありません。この事象は記録・報告されます。

$ su
パスワード: 
su: 認証失敗

解決方法

How to Fix "Username is not in the sudoers file. This incident will be reported" in Ubuntu

こちらのサイトにまさに求めていた答えが書いてありました。 単純にsudoersファイルが壊れてしまったようですね。 Ubuntuリカバリモードで起動して、ユーザにsudo権限を与えます。

以下は上記のサイトの手順に沿って進めます。 画像は上記のサイトから拝借致しました。


PCを再起動してブート画面でAdvanced options for Ubuntuを選びます。ブート画面へは起動中にShiftキー長押しでいけます。

f:id:dorapon2000:20181025141358p:plain

recovery modeを選びます。自分のときはバージョン違いで2つあったんですが、新しい方のバージョンでやりました。

f:id:dorapon2000:20181025141819p:plain

Recovery menuでrootを選びます。ここからシェルモードに移ります。

f:id:dorapon2000:20181025142020p:plain

Press Enter for maintenanceと出るのでEnter押します。

参考サイトではいくつか方法を示されていましたが、コマンド打つだけの簡単な方法を実行しました。usernameには存在する自身のユーザ名を入れてください。

# mount -o rw,remount /
# adduser username sudo
# exit 

resume -> OKと進み、再起動すると無事sudoが使えるようになっています。

f:id:dorapon2000:20181025142731p:plain f:id:dorapon2000:20181025142745p:plain

🎉🎉

参考サイト

Ubuntu日本語フォーラム / 管理者としての権限が必要な操作でのパスワードが通らなくなりました

qiita.com

ns3.29のcodelのサンプルコードでSojournTimeを正しくトレーシングできない

正確には、ns-3-dev-git/codel-vs-pfifo-asymmetric.cc at master · nsnam/ns-3-dev-git · GitHubのSojournTimeを正しくトレーシングできません。その値をトレーシングしない以外は正常に動いていました。

特定の値の推移を記録できるトレーシングの仕組みについては、公式チュートリアルに詳しい説明があります。

環境

問題

github.com

codel-vs-pfifo-asymmetric.ccはns3に同封されているサンプルコードで、CoDelの性能評価することができます。 特にDroppingState・SojournTime・QueueLengthなどCoDelの性質を知るために必要な値をトレースできます。

問題は、SojournTimeだけなぜか出力ファイルが空白になってしまっていることです。 本来ならばcodel-vs-pfifo-fast-asymmetric-CoDel-sojourn.trにSojournTimeの値が時系列順に列挙されているはずです。

しかし、それ以外のトレースソースについては値をトレースできていますし、プログラム自体もエラーを出しません。

むむむ🤔

修正場所

2箇所修正すべき箇所があります。

$ diff -u codel-vs-pfifo-asymmetric.cc.orig codel-vs-pfifo-asymmetric.cc
--- codel-vs-pfifo-asymmetric.cc.orig   2018-10-12 00:50:29.826270000 +0900
+++ codel-vs-pfifo-asymmetric.cc        2018-10-12 00:51:16.568112000 +0900
@@ -92,9 +92,9 @@
 }

 static void
-SojournTracer (Ptr<OutputStreamWrapper>stream, Time oldval, Time newval)
+SojournTracer (Ptr<OutputStreamWrapper>stream, Time val)
 {
-  *stream->GetStream () << oldval << " " << newval << std::endl;
+  *stream->GetStream () << val << std::endl;
 }

 static void
@@ -109,7 +109,7 @@
   else
     {
       Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream (sojournTrFileName.c_str ());
-      Config::ConnectWithoutContext ("/NodeList/2/$ns3::TrafficControlLayer/RootQueueDiscList/0/$ns3::CoDelQueueDisc/Sojourn", MakeBoundCallback (&SojournTracer, stream));
+      Config::ConnectWithoutContext ("/NodeList/2/$ns3::TrafficControlLayer/RootQueueDiscList/0/$ns3::CoDelQueueDisc/SojournTime", MakeBoundCallback (&SojournTracer, stream));
     }
 }

1箇所目は、Sojournというトレースシンク名で、正しくはSojournTimeでした。

  • SojournTime: Sojourn time of the last packet dequeued from the queue disc Callback signature: ns3::Time::TracedCallback

@ ns-3: ns3::CoDelQueueDisc Class Reference

2箇所目は、SojournTimeのコールバック関数のシグネチャが違いました。 上の記述にもCallback signature: ns3::Time::TracedCallbackとありますが、このシグネチャは引数を1つしか持ちません。

typedef void(* ns3::Time::TracedCallback) (Time value)

@ ns-3: ns3::Time Class Reference

当のコールバック関数SojournTracerはstreamと合わせて引数が2つじゃないかと思われるかもしれませんが、streamはns3の便利機能の1つで、いわばおまけです。 MakeBoundCallbackでファイルストリームをコールバック関数に渡すことでファイルに結果を出力してくれます。

過去の情報が修正されずに残ってしまったという感じでしょうか。

出力結果の可視化

トレース結果はgnuplotなどで可視化したいので、下に示すコードのように、時刻の値とsojournTimeの値を並べて出力するのがいいと思います。

static void
SojournTracer (Ptr<OutputStreamWrapper>stream, Time val)
{
  *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << val.GetMilliSeconds() << std::endl;
}