20201130のLinuxに関する記事は11件です。

Docker上のCentOSだと自作systemdが動かない時の対応方法

どういう状況だってばよ!?

  1. CentOSで定期実行を実現する為にsystemdを自作したい。
  2. 実機のCentOSだと自作systemdが動くのに、Docker上のCentOSだとなぜかダメ。
  3. 具体的にはDocker上だと下記のエラーでこける。

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

あたいはこんな環境でやってます

この記事は下図のようにWindows10のDocker Desktopをインストール済で、Docker-composeももれなくセットでインストールされている前提になります。
image.png

まずはdocker-compose.ymlを新規作成

どこかのフォルダにdocker-compose.ymlという設定ファイルがある訳ではないです。
また、docker-compose.ymlを置く場所はひとまずどこでもよかとです。

Docker初心者なので『docker-compose.ymlって設定ファイルどこにあるの…?どこに置かなきゃいけないの…?』なんて右往左往してました…(´・ω・`)

docker-compose.yml ≒ コンテナ作成手順書(指示書) って捉えるといいかな~って思います。

んで、今回は『C:\Users\waokitsune\centos8_systemd_test』というフォルダにdocker-compose.ymlを作成してみました。

docker-compose.ymlの中身

参考サイトさん を参照させてもらいました。
(centosという名前のイメージは既にある前提のymlになります)

version: "3.8"
services:
  centos8_systemd_test:
    image: centos
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    cap_add:
      - SYS_ADMIN
    command: /sbin/init

PowerShellでDocker-composeにymlを食わせる

PowerShellを起動してまずはdocker-composeが置いてある場所へ行き…

cd C:\Users\waokitsune\centos8_systemd_test

docker-composeコマンドでコンテナ作成。

docker-compose up -d

成功するとこんな感じ。
image.png

ymlを食わせて出来たコンテナを使うぞい

Docker Desktopのダッシュボード開いて、端末起動!
ああ…なんか頭痛が痛いみたいなコンテナ名になっちゃってますね…(´・ω・`)
image.png

まずは ps aux でプロセスを見てみましょい。
なんか行けそうな気がします。

image.png

ちなみに自作systemdが動かなかったコンテナの ps aux 結果はこちら。
image.png

テキストファイルを作成するシェルスクリプトファイル『zoi.sh』をルート直下に作成します。

zoi.sh
#!/usr/bin/bash
touch /zoizoi.txt

作ったシェルスクリプトファイルに実行権限を与えてあげます。

chmod 755 /zoi.sh

そして、『/etc/systemd/system』フォルダーに『zoi.service』ファイルを作成します。
作ったシェルスクリプトをキックするだけの簡単なやつです。

zoi.service
[Unit]
Description=kyoumoitinitigannbaruzoi

[Service]
Type=simple
ExecStart=/zoi.sh

[Install]
WantedBy=multi-user.target

準備ができたので『zoi.service』を起動してみます。

systemctl start zoi.service

エラー無く終了したっぽいです。
image.png
本当か?本当にそうかぁ~?
systemctl status zoi.service で確認。
image.png
白丸なので正常終了っぽいです。
(シェルスクリプトに実行権限与え忘れてサービス起動した痕跡があるのはモアイ教ご愛敬)

ls / でも確認。
image.png
シェルスクリプトによってテキストファイルが作成されてます。

OKっす。

無事、Docker上のCentOSで自作systemdを動かせました。

蛇足

docker-compose.ymlがあると『まったく同じ環境をまた作る』が簡単にできて便利だと思いました。

参考サイトさん

https://futureys.tokyo/lets-run-the-web-application-for-development-by-docker-desktop-and-access-it-by-browser/

バージョン

Windows10 Pro バージョン1909 OSビルド19042.630
Docker Desktop:2.5.0.1(49550) Engine:19.03.13 Compose:1.27.4
PSVersion 5.1.19041.610
CentOS Linux release 8.2.2004 (Core)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux ウェルノウンポート

【Linux ウェルノウンポート】

LPIC102 覚えておくべき代表的なウェルノウンポート

20 FTP TCP ファイル転送(データ用)

21 FTP TCP ファイル転送(制御用)

22 SSH TCP リモートホストの遠隔操作(暗号化有り)

23 Telnet TCP リモートホストの遠隔操作(暗号化無し)

25 SMTP TCP 電子メール送信

53 DNS TCP/UDP 名前解決

80 HTTP TCP テキストや画像などのコンテンツの送受信(暗号化無し)

110 POP3 TCP 電子メール受信

143 IMAP TCP 電子メール受信

443 HTTPS TCP テキストや画像などのコンテンツの送受信(暗号化有り)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux シェルスクリプト

【Linux シェルスクリプト】

シェルスクリプト 構文

・if構文

if コマンド1
 コマンド2
fi

・test構文

test 条件式

・for構文

for シェル変数 in 値リスト
do 
   コマンド
done

・while構文

while コマンド1
do 
   コマンド2
done

・seq 構文

seq 終了値
seq 初期値 終了値 
seq 初期値 増分 終了値
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux 特殊なシェル変数

【Linux 特殊なシェル変数】

特殊なシェル変数まとめ

$$ シェルのPID

$? 最後に実行したコマンドの終了値

$# 引数の個数

$* 区切り文字で区切られた全ての引数(デフォルトは空文字)

$0 実行ファイル名

$1... 1番目の引数、2番目の引数...

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Go言語で作成した実行ファイルをEC2でデーモンとして実行する

概要

Go言語でbuildした実行ファイルをEC2上に配置しdeamon化します。
そうして、EC2の起動時に自動的にGoでビルドしたWebサーバを実行させます。

経緯

Go言語+GinでビルドしたWebサーバをEC2上で構築していたのですが、
EC2の起動時に自動実行されなかったのでいろいろと試した結果、デーモン化しinit.dで自動起動させました。

1 ビルドした実行ファイルのデーモン化

ディレクトリ
/etc/systemd/system/サービス名.service

[Unit]
Description=説明文

[Service]
User=root
Group=root
WorkingDirectory=ディレクトリ
ExecStart=ディレクトリ/実行ファイル名
Restart=always
KillMode=process

[Install]
WantedBy=multi-user.target

サービスの確認

systemctl status サービス名.service
systemctl start サービス名.service
systemctl stop サービス名.service

上記でサービスの起動が出来たらデーモン化は完了です。

2. init.dでサービスの自動起動を設定

ディレクトリ
/etc/int.d/app_start
--------------init.d 内容-------------------------
#!/bin/sh
# chkconfig: 2345 99 10
# description: deamon wakeup scrupt

case "$1" in
 start)
       date >> /home/user/start.txt
       echo "start!" >> /home/user/app_start.log
       sudo sh /home/user/scripts/application_start_server.sh
       ;;
 stop)
       echo date >> /home/user/app_stop.log
       sudo sh /home/user/scripts/application_stop_server.sh
       ;;
  *) break ;;
esac

application_start_server.sh の部分は直接コマンドを書いても良いですし、
今回はシェルスクリプトを実行させました。
(サービスの起動・停止時に時間をファイルに出力しています。)

3 確認

EC2を再起動しサービスが正常に起動していれば完了です。

所感

インスタンスの再起動は物理マシンの起動と挙動が違うので、
その辺りが原因でバッチ処理ではうまく動かなかったのだと考えています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

個人開発でも気軽に使える Copy Protection サービスをつくりました

この記事は個人開発 Advent Calendar 2020 6日目の記事です。

昨日は @yakipudding さんによる「Reactで作成したポートフォリオサイトをNextに移行した」でした。
改良後のデザインがおっしゃられるとおりとてもスッキリしていて、センスの良さが本当に羨ましかったです。

はじめに

作った理由はこちらに書いたとおりです

3ヶ月ぐらいでできるかと見積もっていたのですが実際はリリースまで6ヶ月もかかってしまい、自分の effort estimation の精度に自信をなくして落ち込んだりもしたのですが、単に私の productivity が普通のエンジニアの半分ぐらいしかなかっただけなのかもしれない1と気をとりなおして今は元気な私はソフトウェア工学屋崩れ2の野良犬です
(U^ω^)

関係ないのですが Software Engineering at Google 読んでて、エンピリカルなソフトウェア工学屋さんの言ういわゆる effort の事を一貫して endeavor って呼んでるのが珍しい言い方3だなとおもいました

こちらでは RPi の話しか書かなかったのですが、RPi4 だけでなく Linux でも Mac でも使える汎用5のコピープロテクションですので、皆様もこちらに書いたみたいな目にあったりされましたら(されないように)使っていただければと思いまして、老爺心ながら使い方をご紹介させていただきます次第です

サービスの紹介

KoshitnoSansi ライブラリと共にアプリケーションのコピープロテクションを提供するクライアント - サーバ型の No license file な application anti-piracy サービスです

コピープロテクションって一般にライセンス定義ファイルとかライセンスキーとかを使ってアプリケーションを unauthorized なコピーから保護するものなのですが、ストレージがむき出しな RPi だとそれが弱点になると考え、それらを使わないで実現するためにクライアント-サーバ型で実装しました

クライアント-サーバ型であることで、ネットワークに接続していないスタンドアロンなアプリでは利用できないというネガティブな副作用があるのですが、逆に、扱いが煩わしく失敗すると事故の原因になりかねないライセンスファイルをつかわないですむのでお気軽お手軽というポジティブな副作用も生じております。世の中捨てる神あれば拾う神あり、人生全て塞翁が馬ということなのでございましょう

koshinto と sansi のコピープロテクションの仕組み

こちらに書いたとおりなのですが、sansi ライブラリはユーザーがダウンロードする時からその内部にアプリケーションの束縛条件を一意に表す ID (以下、Bind_id と呼びます)をバイナリで埋め込んであります

sansi ライブラリの提供する confirm() 関数は、呼ばれると各種の環境情報(デバイスのシリアルナンバー、IP アドレス、Mac アドレス等)を収集して、Bind_id と一緒に Koshinto に送信します

koshinto サーバは sansi から送信された情報と、内部に保存するアプリケーションの束縛条件をチェックして、OK/NG の返答をセキュアに返します

koshinto からの OK/NG の応答を confirm() は戻り値でアプリケーションにします

以上、アプリケーションは起動時に confirm() を呼んで、戻り値が NG だったら exit するように一文を入れるだけで copy protection の実装が完了するわけでございます。これは簡単!

スクリーンショット 2020-11-22 12.35.21.png

この仕組自体の anti-tamper についてはこちらに紹介いたしました

使用例

サンプルアプリケーション

10秒間の秒読みを行う、シチュエーションによってはとても practical なアプリケーションです

main.simple.c
/*
* 10 second countdown, copy guarded by sansi
* 
* @author Dr. Takeyuki UEDA
* @copyright Copyright© Atelier UEDA 2020 - All rights reserved.
*/

#include <stdio.h>  // for printf
#include <unistd.h> // for seep
void tenseccount();

int main(){

  tenseccount();
  return 0;
}

void tenseccount(){
  int i;
  printf("start 10 second countdown\n");
  for (i=10; i>0; i--){
    printf("%d\n",i);
    sleep(1);
  }
  printf("0!\n");
}

Practical なので悪意の第三者による意図せぬコピー、著作権侵害をふせぐために sansi を組み込んで保護しましょう

sansi の組み込み

main.simple.c
/*
* 10 second countdown, copy guarded by sansi
* 
* @author Dr. Takeyuki UEDA
* @copyright Copyright© Atelier UEDA 2020 - All rights reserved.
*/

#include "sansi.h"  // for sansi libraries

#include <stdio.h>  // for printf
#include <unistd.h> // for seep
void tenseccount();

int main(){

  if (ok_confirmed == confirm(NULL, NULL, NULL)){
    printf("OK\n");
  } else {
    printf("NG\n");
    return -1;
  }

  tenseccount();
  return 0;
}

void tenseccount(){
  int i;
  printf("start 10 second countdown\n");
  for (i=10; i>0; i--){
    printf("%d\n",i);
    sleep(1);
  }
  printf("0!\n");
}

追加したのは以下の2点で
- 8行目: sansi.h のインクルード
- 16-21行目: アプリの最初に confirm() を呼び、戻り値が ok_confirmed でなければ異常終了

サンプルプロジェクトの clone

完成品はこちらにございますので、git clone して

MacBook-Air:tmp takeyuki$ git clone https://github.com/UedaTakeyuki/sansi_examples.git

sansi_examples/c フォルダに移動してください

MacBook-Air:tmp takeyuki$ cd sansi_examples/c

ls してみるといろいろなファイルがあります

MacBook-Air:c takeyuki$ ls
README.md   compile.sh  main.c      main.simple.c   sansi.h

左からそれぞれ README、 compile スクリプト、別のサンプルの main.c (本稿ではつかいません)、先程紹介した main.simple.c、そして sansi のヘッダーファイルです

ここでは紹介しませんが、C アプリの他に go, python, bash の組込例も用意させていただきました
go は cgo で sansi をリンクする例をご紹介させていただきました。vlang も同様にできるように思っているのですけどまだ試せていません。どなたか pull req いただければ感謝の言葉もございません
python は nuitka でコンパイルして strip すること、bash は shc とかでバイナリ化する前提です

sansi のダウンロード

Koshinto にログインして Home から [Binds]-[All] を選択してください

スクリーンショット 2020-11-30 18.29.08.png

アカウントを作った直後だと、一つだけですが Bind がすでにあるのでこれを選択して

スクリーンショット 2020-11-30 18.28.51.png

メニューから Sansi library Download を開き
スクリーンショット 2020-11-30 18.29.24.png

アプリケーションのターゲットに合わせてライブラリをダウンロードしてください

スクリーンショット 2020-11-30 18.29.37.png

ダウンロードしたライブラリを先程 git clone したプロジェクトにコピーしてください

MacBook-Air:c takeyuki$ cp /Users/takeyuki/Downloads/libsansi_ZbPdGoGyrNkQ_mac_v1.1.o .
MacBook-Air:c takeyuki$ ls
README.md               main.c
compile.sh              main.simple.c
libsansi_ZbPdGoGyrNkQ_mac_v1.1.o    sansi.h

アプリケーションのコンパイル

コンパイルスクリプトの使い方は

MacBook-Air:c takeyuki$ ./compile.sh -h
Usage: ./compile.sh [-h][-c][-g][-m][-o obj] [source] [libsansi]
  [source]:   compiling source file, default is 'main.sample.c' 
  [libsansi]: path for linking 'libsansi….o', default is found it in cwd automatically 
  [-h]: show this usage and exit
  [-c]: compile for linux by clang
  [-g]: compile for linux by gcc, this is default
  [-m]: compile for mac by clang
  [-o obj] set compiled object file name, default is a.out
MacBook-Air:c takeyuki$ ./compile.sh -m

デフォルトで main.sample.c をコンパイルして、デフォルトで a.out をつくります。デフォルトで sansi ライブラリをよしなにさがしてくれるので便利です

Mac 用のコンパイルの場合

Mac 用のコンパイルであることを指示する -m を指定する必要があります
bash:
MacBook-Air:c takeyuki$ ./compile.sh -m
source = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_mac_v1.1.o
compiler = clang
obj = a.out
compiling…

尚、sansi は OpenSSL に依存するのですが、Mac だと OpenSSL がインストールされていないかもしれません。その旨のエラーがでた場合はインストールしてください

Linux 用のコンパイルの場合

Linux の場合はなにも指定する必要がありません

pi@raspberrypi:~/sansi_examples/c $ ./compile.sh 
source   = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o
compiler = gcc
obj      = a.out
compiling…

-c を指定すると gcc の代わりに clang でコンパイルします

pi@raspberrypi:~/sansi_examples/c $ ./compile.sh -c
source   = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o
compiler = clang
obj      = a.out
compiling…

例1. アプリケーションを Mac のシリアル番号に束縛する

Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです

スクリーンショット 2020-11-30 17.23.33.png

アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind

正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください

1. 事前に取得した key の値に直接束縛する場合

Koshinto に戻って Bind の [Keys] を開きます

スクリーンショット 2020-11-30 19.45.28.png

調べておいた Mac のシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします
スクリーンショット 2020-11-30 19.53.15.png

Status を開き、Binding を選択して右下の UPDATE をクリックします
スクリーンショット 2020-12-02 18.56.05.png

Mac に戻って a.out がブロックされずに実行できているのが確認できます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

2. sansi が取得して送信してきた値から選択して束縛する場合

現在の status は Not Active なので
スクリーンショット 2020-11-30 17.23.24.png

Bind Waiting に変更して
スクリーンショット 2020-11-30 17.32.06.png

右下の UPDATE をクリックします
スクリーンショット 2020-11-30 17.32.15.png

Mac に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずです

MacBook-Air:c takeyuki$ ./a.out
NG

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys を開くと値が送信されてきています

スクリーンショット 2020-11-30 17.34.59.png

Platform Serial Number の lock を✓して右下の UPDATE をクリックします

スクリーンショット 2020-11-30 17.35.08.png

Status は Bind Waiting から Bind Requesting に遷移しています

スクリーンショット 2020-11-30 17.33.26.png

Status を Binding に変更します

スクリーンショット 2020-11-30 17.33.43.png

変更したら右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.35.33.png

Mac に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合

アプリケーションが最初に起動された Mac のシリアルナンバーに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.22.36.png

現在の Status は Not Active なので

スクリーンショット 2020-11-30 17.23.33.png

Auto Bind Waiting に変更します

スクリーンショット 2020-11-30 17.23.47.png

スクリーンショット 2020-11-30 17.24.00.png

Mac に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys の値は sansi が収集して送信してきた値に更新されていて、Platform Serial Number も更新されています

スクリーンショット 2020-11-30 17.25.17.png

Status は Binding に遷移しています

スクリーンショット 2020-11-30 17.25.04.png

例2. アプリケーションを RaspberryPi の SDカードのシリアルIDに束縛する

Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです

スクリーンショット 2020-11-30 17.23.33.png

アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind

正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください

1. 事前に取得した key の値に直接束縛する場合

Koshinto に戻って Bind の [Keys] を開きます

スクリーンショット 2020-11-30 19.45.28.png

調べておいた SD カードのシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします

スクリーンショット 2020-12-02 18.49.24.png

Status を開き、Binding を選択して右下の UPDATE をクリックします
スクリーンショット 2020-12-02 18.56.05.png

Raspberry Pi に戻って a.out がブロックされずに実行できているのが確認できます

pi@raspberrypi:~/sansi_examples/c $ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

2. sansi が取得して送信してきた値から選択して束縛する場合

現在の status は Not Active なので
スクリーンショット 2020-11-30 17.23.24.png

Bind Waiting に変更して
スクリーンショット 2020-11-30 17.32.06.png

右下の UPDATE をクリックします
スクリーンショット 2020-11-30 17.32.15.png

Raspberry Pi に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずです

pi@raspberrypi:~/sansi_examples/c $ ./a.out
NG

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys を開くと値が送信されてきています

スクリーンショット 2020-12-02 19.04.58.png

SD Card Serial ID の lock を✓して右下の UPDATE をクリックします

スクリーンショット 2020-12-02 19.09.19.png

Status は Bind Waiting から Bind Requesting に遷移しています

スクリーンショット 2020-11-30 17.33.26.png

Status を Binding に変更します

スクリーンショット 2020-11-30 17.33.43.png

変更したら右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.35.33.png

Raspberry Pi に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます

pi@raspberrypi:~/sansi_examples/c $ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合

アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-12-02 19.12.31.png

現在の Status は Not Active なので

スクリーンショット 2020-11-30 17.23.33.png

Auto Bind Waiting に変更します

スクリーンショット 2020-11-30 17.23.47.png

スクリーンショット 2020-11-30 17.24.00.png

Raspberry Pi に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys の値は sansi が収集して送信してきた値に更新されていて、SD Card Serial ID も更新されています

スクリーンショット 2020-12-02 19.16.54.png

Status は Binding に遷移しています

スクリーンショット 2020-11-30 17.25.04.png

例3. アプリケーションを Linux Server の Global IP address に束縛する

Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです

スクリーンショット 2020-11-30 17.23.33.png

アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind

正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください

1. 事前に取得した key の値に直接束縛する場合

Koshinto に戻って Bind の [Keys] を開きます

スクリーンショット 2020-11-30 19.45.28.png

調べておいた Global IP addressスクリーンショット 2020-12-03 22.54.14.png
を Global IP に入力して lock を✓し、右下の UPDATE をクリックします

スクリーンショット 2020-12-02 20.37.02.png

Status を開き、Binding を選択して右下の UPDATE をクリックします
スクリーンショット 2020-12-02 18.56.05.png

Linux に戻って a.out がブロックされずに実行できているのが確認できます

ueda@amfortas:~/sansi_examples/c$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

2. sansi が取得して送信してきた値から選択して束縛する場合

現在の status は Not Active なので
スクリーンショット 2020-11-30 17.23.24.png

Bind Waiting に変更して
スクリーンショット 2020-11-30 17.32.06.png

右下の UPDATE をクリックします
スクリーンショット 2020-11-30 17.32.15.png

Linux に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずです

ueda@amfortas:~/sansi_examples/c$ ./a.out
NG

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys を開くと値が送信されてきています

スクリーンショット 2020-12-02 19.04.58.png

Global IP の lock を✓して右下の UPDATE をクリックします

スクリーンショット 2020-12-03 22.56.17.png

Status は Bind Waiting から Bind Requesting に遷移しています

スクリーンショット 2020-11-30 17.33.26.png

Status を Binding に変更します

スクリーンショット 2020-11-30 17.33.43.png

変更したら右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.35.33.png

Linux に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます

ueda@amfortas:~/sansi_examples/c$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合

アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-12-03 22.59.42.png

現在の Status は Not Active なので

スクリーンショット 2020-11-30 17.23.33.png

Auto Bind Waiting に変更します

スクリーンショット 2020-11-30 17.23.47.png

スクリーンショット 2020-11-30 17.24.00.png

Linux に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます

ueda@amfortas:~/sansi_examples/c$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys の値は sansi が収集して送信してきた値に更新されていて、Global IP も更新されています

スクリーンショット 2020-12-03 23.03.39.png

Status は Binding に遷移しています

スクリーンショット 2020-11-30 17.25.04.png

詳説

1. Bind の5種類の状態と、アプリケーションを Bind する3通りの方法

正常な Bind のステータスは以下の5つのどれかになります。各ステータスで confirm() の通知を受けた際の戻り値と、koshinto 内の bind の key と status の変化を表にまとめました

status return koshinto の bind の key koshinto 内の bind の status
Not Active 常に ng_comfirmed 変化なし 変化なし
Bind Waiting 常に ng_comfirmed confirm からの値で更新 Bind Requestingに遷移
Bind Requesting 常に ng_comfirmed 変化なし 変化なし
Auto Bind Waiting 常に ok_comfirmed confirm からの値で更新 Binding
Binding confirm からの値によって ng_comfirmed またはok_comfirmed 変化なし 変化なし

Not Active が、Bind が使われていない状態です
Binding が、アプリケーションが束縛されている状態です

アプリケーションを Bind する方法は3種類あって

  1. キーの値を設定してロックし、状態を Binding に変更
  2. 状態を [Bind Waitingに変更]して sansi からの confirm()を待つ。bind の key が更新され、状態が [Bind Requesting] に変わるので、適切な key を選んでロックし、状態を [Binding]に変更
  3. 適切な key を選んでロックしてから状態を [Auto Bind Waitingに変更]して sansi からの confirm()を待つ。key の値が更新されて自動的に [Bind]状態になる

束縛したい key の値(今の場合は Mac のシリアルナンバー)を事前に知っていて(「このマックについて」で確認済で)、その値を使って束縛する場合に 1. の手順になります。調べるのってめんどくさかったり typo があったりすると思うので後述の 2. や 3. の手順をお薦めいたしますが、Bind の状態の推移はシンプルに次のようになります

[Not Active] -> [Bind]

束縛したい key の値を知らない、もしくは自分で調べるのがめんどくさいので sansi に任せたい場合、sansi が送ってくる値を確認して問題がなければその値に束縛する場合が 2. の手順になります。遷移は

[Not Active] -> [Bind Waiting] -> [Bind Requesting] ->[Bind]

確認せずに自動的にその環境に束縛するのが 3. の手順になります。遷移は

[Not Active] -> [Auto Bind Waiting] -> [Binding]

related works

こちらを参照いただければ幸いです

名前の由来

Koshinto と Sansi の名前の由来はこちらを参照賜われれば至福の至に存じます次第です

結び

長々と書いてしまい本当にどうもすみません、今は謹んで反省しております次第です、無駄に長生きした年寄りの話が無駄に長いのは相応というものでございますれば、エンジニアの情けで許してくだされ/(^o^)\

references

明日は

明日は@azukisiromochiさんによる「アプリ名『焼き鳥』事件 ???」です!私は前日なのでメンションもらって限定公開の頃から読ませて頂いてたのですが、正直、ものすごくおもしろい、ためになるお話なんですよ!お楽しみに!


  1. もともと RPi だけの、それも SD CARD と Board の ID だけのつもりだったのに、つい NIC を追加したら Mac や Linux 一般にも欲がでて、という途中からの仕様追加を個人開発なのにやりまくったのも悪かったかもしれません 

  2. 無駄に工学博士持ってます。せっかく博士なんだから、何時の日かガッチャマンみたいな自分の戦隊が欲しいと日々思いつつなんか作ってます。わるもんでもいいけど。それか怪盗グルーとミニヨンみたいな仲間とか 

  3. タイトルに反してそういう人達へのネガティブな感情が前提にあるのかと読んでて勘ぐりました 

  4. Raspberry Pi 以外の各種 IoT ボードも Linux ベースであれば IP address や MAC IDに束縛することで利用可能です。ボード固有のIDのへの束縛も対応していきたく、リファレンスボードの donation を募集してます 

  5. Windows は持ってないので、開発に使える PC の donation を募集しています 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

個人開発でも気軽に使える Copy Protection のサービスをつくりました

この記事は個人開発 Advent Calendar 2020 6日目の記事です。

昨日は @yakipudding さんによる「Reactで作成したポートフォリオサイトをNextに移行した」でした。
改良後のデザインがおっしゃられるとおりとてもスッキリしていて、センスの良さが本当に羨ましかったです。

はじめに

作った理由はこちらに書いたとおりです

3ヶ月ぐらいでできるかと見積もっていたのですが実際はリリースまで6ヶ月もかかってしまい、自分の effort estimation の精度に自信をなくして落ち込んだりもしたのですが、単に私の productivity が普通のエンジニアの半分ぐらいしかなかっただけなのかもしれない1と気をとりなおして今は元気な私はソフトウェア工学屋崩れ2の野良犬です
(U^ω^)

関係ないのですが Software Engineering at Google 読んでて、エンピリカルなソフトウェア工学屋さんの言ういわゆる effort の事を一貫して endeavor って呼んでるのが珍しい言い方3だなとおもいました

こちらでは RPi の話しか書かなかったのですが、RPi4 だけでなく Linux でも Mac でも使える汎用5のコピープロテクションですので、皆様もこちらに書いたみたいな目にあったりされましたら(されないように)使っていただければと思いまして、老爺心ながら使い方をご紹介させていただきます次第です

サービスの紹介

KoshitnoSansi ライブラリと共にアプリケーションのコピープロテクションを提供するクライアント - サーバ型の No license file な application anti-piracy サービスです

コピープロテクションって一般にライセンス定義ファイルとかライセンスキーとかを使ってアプリケーションを unauthorized なコピーから保護するものなのですが、ストレージがむき出しな RPi だとそれが弱点になると考え、それらを使わないで実現するためにクライアント-サーバ型で実装しました

クライアント-サーバ型であることで、ネットワークに接続していないスタンドアロンなアプリでは利用できないというネガティブな副作用があるのですが、逆に、扱いが煩わしく失敗すると事故の原因になりかねないライセンスファイルをつかわないですむのでお気軽お手軽というポジティブな副作用も生じております。世の中捨てる神あれば拾う神あり、人間万事塞翁が馬ということなのでございましょう

koshinto と sansi のコピープロテクションの仕組み

こちらに書いたとおりなのですが、sansi ライブラリはユーザーがダウンロードする時からその内部にアプリケーションの束縛条件を一意に表す ID (以下、Bind_id と呼びます)をバイナリで埋め込んであります

sansi ライブラリの提供する confirm() 関数は、呼ばれると各種の環境情報(デバイスのシリアルナンバー、IP アドレス、Mac アドレス等)を収集して、Bind_id と一緒に Koshinto に送信します

koshinto サーバは sansi から送信された情報と、内部に保存するアプリケーションの束縛条件をチェックして、OK/NG の返答をセキュアに返します

koshinto からの OK/NG の応答を confirm() は戻り値でアプリケーションにします

以上、アプリケーションは起動時に confirm() を呼んで、戻り値が NG だったら exit するように一文を入れるだけで copy protection の実装が完了するわけでございます。これは簡単!

スクリーンショット 2020-11-22 12.35.21.png

この仕組自体の anti-tamper についてはこちらに紹介いたしました

使用例

サンプルアプリケーション

10秒間の秒読みを行う、シチュエーションによってはとても practical なアプリケーションです

main.simple.c
/*
* 10 second countdown, copy guarded by sansi
* 
* @author Dr. Takeyuki UEDA
* @copyright Copyright© Atelier UEDA 2020 - All rights reserved.
*/

#include <stdio.h>  // for printf
#include <unistd.h> // for seep
void tenseccount();

int main(){

  tenseccount();
  return 0;
}

void tenseccount(){
  int i;
  printf("start 10 second countdown\n");
  for (i=10; i>0; i--){
    printf("%d\n",i);
    sleep(1);
  }
  printf("0!\n");
}

Practical なので悪意の第三者による意図せぬコピー、著作権侵害をふせぐために sansi を組み込んで保護しましょう

sansi の組み込み

main.simple.c
/*
* 10 second countdown, copy guarded by sansi
* 
* @author Dr. Takeyuki UEDA
* @copyright Copyright© Atelier UEDA 2020 - All rights reserved.
*/

#include "sansi.h"  // for sansi libraries

#include <stdio.h>  // for printf
#include <unistd.h> // for seep
void tenseccount();

int main(){

  if (ok_confirmed == confirm(NULL, NULL, NULL)){
    printf("OK\n");
  } else {
    printf("NG\n");
    return -1;
  }

  tenseccount();
  return 0;
}

void tenseccount(){
  int i;
  printf("start 10 second countdown\n");
  for (i=10; i>0; i--){
    printf("%d\n",i);
    sleep(1);
  }
  printf("0!\n");
}

追加したのは以下の2点で
- 8行目: sansi.h のインクルード
- 16-21行目: アプリの最初に confirm() を呼び、戻り値が ok_confirmed でなければ異常終了

サンプルプロジェクトの clone

完成品はこちらにございますので、git clone して

MacBook-Air:tmp takeyuki$ git clone https://github.com/UedaTakeyuki/sansi_examples.git

sansi_examples/c フォルダに移動してください

MacBook-Air:tmp takeyuki$ cd sansi_examples/c

ls してみるといろいろなファイルがあります

MacBook-Air:c takeyuki$ ls
README.md   compile.sh  main.c      main.simple.c   sansi.h

左からそれぞれ README、 compile スクリプト、別のサンプルの main.c (本稿ではつかいません)、先程紹介した main.simple.c、そして sansi のヘッダーファイルです

ここでは紹介しませんが、C アプリの他に go, python, bash の組込例も用意させていただきました
go は cgo で sansi をリンクする例をご紹介させていただきました。vlang も同様にできるように思っているのですけどまだ試せていません。どなたか pull req いただければ感謝の言葉もございません
python は nuitka でコンパイルして strip すること、bash は shc とかでバイナリ化する前提です

sansi のダウンロード

Koshinto にログインして Home から [Binds]-[All] を選択してください

スクリーンショット 2020-11-30 18.29.08.png

アカウントを作った直後だと、一つだけですが Bind がすでにあるのでこれを選択して

スクリーンショット 2020-11-30 18.28.51.png

メニューから Sansi library Download を開き
スクリーンショット 2020-11-30 18.29.24.png

アプリケーションのターゲットに合わせてライブラリをダウンロードしてください

スクリーンショット 2020-11-30 18.29.37.png

ダウンロードしたライブラリを先程 git clone したプロジェクトにコピーしてください

MacBook-Air:c takeyuki$ cp /Users/takeyuki/Downloads/libsansi_ZbPdGoGyrNkQ_mac_v1.1.o .
MacBook-Air:c takeyuki$ ls
README.md               main.c
compile.sh              main.simple.c
libsansi_ZbPdGoGyrNkQ_mac_v1.1.o    sansi.h

アプリケーションのコンパイル

コンパイルスクリプトの使い方は

MacBook-Air:c takeyuki$ ./compile.sh -h
Usage: ./compile.sh [-h][-c][-g][-m][-o obj] [source] [libsansi]
  [source]:   compiling source file, default is 'main.sample.c' 
  [libsansi]: path for linking 'libsansi….o', default is found it in cwd automatically 
  [-h]: show this usage and exit
  [-c]: compile for linux by clang
  [-g]: compile for linux by gcc, this is default
  [-m]: compile for mac by clang
  [-o obj] set compiled object file name, default is a.out
MacBook-Air:c takeyuki$ ./compile.sh -m

デフォルトで main.sample.c をコンパイルして、デフォルトで a.out をつくります。デフォルトで sansi ライブラリをよしなにさがしてくれるので便利です

Mac 用のコンパイルの場合

Mac 用のコンパイルであることを指示する -m を指定する必要があります
bash:
MacBook-Air:c takeyuki$ ./compile.sh -m
source = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_mac_v1.1.o
compiler = clang
obj = a.out
compiling…

尚、sansi は OpenSSL に依存するのですが、Mac だと OpenSSL がインストールされていないかもしれません。その旨のエラーがでた場合はインストールしてください

Linux 用のコンパイルの場合

Linux の場合はなにも指定する必要がありません

pi@raspberrypi:~/sansi_examples/c $ ./compile.sh 
source   = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o
compiler = gcc
obj      = a.out
compiling…

-c を指定すると gcc の代わりに clang でコンパイルします

pi@raspberrypi:~/sansi_examples/c $ ./compile.sh -c
source   = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o
compiler = clang
obj      = a.out
compiling…

例1. アプリケーションを Mac のシリアル番号に束縛する

Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです

スクリーンショット 2020-11-30 17.23.33.png

アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind

正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください

1. 事前に取得した key の値に直接束縛する場合

Koshinto に戻って Bind の [Keys] を開きます

スクリーンショット 2020-11-30 19.45.28.png

調べておいた Mac のシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします
スクリーンショット 2020-11-30 19.53.15.png

Status を開き、Binding を選択して右下の UPDATE をクリックします
スクリーンショット 2020-12-02 18.56.05.png

Mac に戻って a.out がブロックされずに実行できているのが確認できます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

2. sansi が取得して送信してきた値から選択して束縛する場合

現在の status は Not Active なので
スクリーンショット 2020-11-30 17.23.24.png

Bind Waiting に変更して
スクリーンショット 2020-11-30 17.32.06.png

右下の UPDATE をクリックします
スクリーンショット 2020-11-30 17.32.15.png

Mac に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずです

MacBook-Air:c takeyuki$ ./a.out
NG

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys を開くと値が送信されてきています

スクリーンショット 2020-11-30 17.34.59.png

Platform Serial Number の lock を✓して右下の UPDATE をクリックします

スクリーンショット 2020-11-30 17.35.08.png

Status は Bind Waiting から Bind Requesting に遷移しています

スクリーンショット 2020-11-30 17.33.26.png

Status を Binding に変更します

スクリーンショット 2020-11-30 17.33.43.png

変更したら右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.35.33.png

Mac に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合

アプリケーションが最初に起動された Mac のシリアルナンバーに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.22.36.png

現在の Status は Not Active なので

スクリーンショット 2020-11-30 17.23.33.png

Auto Bind Waiting に変更します

スクリーンショット 2020-11-30 17.23.47.png

スクリーンショット 2020-11-30 17.24.00.png

Mac に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys の値は sansi が収集して送信してきた値に更新されていて、Platform Serial Number も更新されています

スクリーンショット 2020-11-30 17.25.17.png

Status は Binding に遷移しています

スクリーンショット 2020-11-30 17.25.04.png

例2. アプリケーションを RaspberryPi の SDカードのシリアルIDに束縛する

Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです

スクリーンショット 2020-11-30 17.23.33.png

アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind

正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください

1. 事前に取得した key の値に直接束縛する場合

Koshinto に戻って Bind の [Keys] を開きます

スクリーンショット 2020-11-30 19.45.28.png

調べておいた SD カードのシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします

スクリーンショット 2020-12-02 18.49.24.png

Status を開き、Binding を選択して右下の UPDATE をクリックします
スクリーンショット 2020-12-02 18.56.05.png

Raspberry Pi に戻って a.out がブロックされずに実行できているのが確認できます

pi@raspberrypi:~/sansi_examples/c $ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

2. sansi が取得して送信してきた値から選択して束縛する場合

現在の status は Not Active なので
スクリーンショット 2020-11-30 17.23.24.png

Bind Waiting に変更して
スクリーンショット 2020-11-30 17.32.06.png

右下の UPDATE をクリックします
スクリーンショット 2020-11-30 17.32.15.png

Raspberry Pi に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずです

pi@raspberrypi:~/sansi_examples/c $ ./a.out
NG

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys を開くと値が送信されてきています

スクリーンショット 2020-12-02 19.04.58.png

SD Card Serial ID の lock を✓して右下の UPDATE をクリックします

スクリーンショット 2020-12-02 19.09.19.png

Status は Bind Waiting から Bind Requesting に遷移しています

スクリーンショット 2020-11-30 17.33.26.png

Status を Binding に変更します

スクリーンショット 2020-11-30 17.33.43.png

変更したら右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.35.33.png

Raspberry Pi に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます

pi@raspberrypi:~/sansi_examples/c $ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合

アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-12-02 19.12.31.png

現在の Status は Not Active なので

スクリーンショット 2020-11-30 17.23.33.png

Auto Bind Waiting に変更します

スクリーンショット 2020-11-30 17.23.47.png

スクリーンショット 2020-11-30 17.24.00.png

Raspberry Pi に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます

MacBook-Air:c takeyuki$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys の値は sansi が収集して送信してきた値に更新されていて、SD Card Serial ID も更新されています

スクリーンショット 2020-12-02 19.16.54.png

Status は Binding に遷移しています

スクリーンショット 2020-11-30 17.25.04.png

例3. アプリケーションを Linux Server の Global IP address に束縛する

Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです

スクリーンショット 2020-11-30 17.23.33.png

アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind

正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください

1. 事前に取得した key の値に直接束縛する場合

Koshinto に戻って Bind の [Keys] を開きます

スクリーンショット 2020-11-30 19.45.28.png

調べておいた Global IP addressスクリーンショット 2020-12-03 22.54.14.png
を Global IP に入力して lock を✓し、右下の UPDATE をクリックします

スクリーンショット 2020-12-02 20.37.02.png

Status を開き、Binding を選択して右下の UPDATE をクリックします
スクリーンショット 2020-12-02 18.56.05.png

Linux に戻って a.out がブロックされずに実行できているのが確認できます

ueda@amfortas:~/sansi_examples/c$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

2. sansi が取得して送信してきた値から選択して束縛する場合

現在の status は Not Active なので
スクリーンショット 2020-11-30 17.23.24.png

Bind Waiting に変更して
スクリーンショット 2020-11-30 17.32.06.png

右下の UPDATE をクリックします
スクリーンショット 2020-11-30 17.32.15.png

Linux に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずです

ueda@amfortas:~/sansi_examples/c$ ./a.out
NG

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys を開くと値が送信されてきています

スクリーンショット 2020-12-02 19.04.58.png

Global IP の lock を✓して右下の UPDATE をクリックします

スクリーンショット 2020-12-03 22.56.17.png

Status は Bind Waiting から Bind Requesting に遷移しています

スクリーンショット 2020-11-30 17.33.26.png

Status を Binding に変更します

スクリーンショット 2020-11-30 17.33.43.png

変更したら右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-11-30 17.35.33.png

Linux に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます

ueda@amfortas:~/sansi_examples/c$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合

アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます

スクリーンショット 2020-12-03 22.59.42.png

現在の Status は Not Active なので

スクリーンショット 2020-11-30 17.23.33.png

Auto Bind Waiting に変更します

スクリーンショット 2020-11-30 17.23.47.png

スクリーンショット 2020-11-30 17.24.00.png

Linux に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます

ueda@amfortas:~/sansi_examples/c$ ./a.out
OK
start 10 second countdown
10
9
8
7
6
5
4
3
2
1
0!

現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします

スクリーンショット 2020-11-30 17.24.15.png

keys の値は sansi が収集して送信してきた値に更新されていて、Global IP も更新されています

スクリーンショット 2020-12-03 23.03.39.png

Status は Binding に遷移しています

スクリーンショット 2020-11-30 17.25.04.png

詳説

1. Bind の5種類の状態と、アプリケーションを Bind する3通りの方法

正常な Bind のステータスは以下の5つのどれかになります。各ステータスで confirm() の通知を受けた際の戻り値と、koshinto 内の bind の key と status の変化を表にまとめました

status return koshinto の bind の key koshinto 内の bind の status
Not Active 常に ng_comfirmed 変化なし 変化なし
Bind Waiting 常に ng_comfirmed confirm からの値で更新 Bind Requestingに遷移
Bind Requesting 常に ng_comfirmed 変化なし 変化なし
Auto Bind Waiting 常に ok_comfirmed confirm からの値で更新 Binding
Binding confirm からの値によって ng_comfirmed またはok_comfirmed 変化なし 変化なし

Not Active が、Bind が使われていない状態です
Binding が、アプリケーションが束縛されている状態です

アプリケーションを Bind する方法は3種類あって

  1. キーの値を設定してロックし、状態を Binding に変更
  2. 状態を [Bind Waitingに変更]して sansi からの confirm()を待つ。bind の key が更新され、状態が [Bind Requesting] に変わるので、適切な key を選んでロックし、状態を [Binding]に変更
  3. 適切な key を選んでロックしてから状態を [Auto Bind Waitingに変更]して sansi からの confirm()を待つ。key の値が更新されて自動的に [Bind]状態になる

束縛したい key の値(今の場合は Mac のシリアルナンバー)を事前に知っていて(「このマックについて」で確認済で)、その値を使って束縛する場合に 1. の手順になります。調べるのってめんどくさかったり typo があったりすると思うので後述の 2. や 3. の手順をお薦めいたしますが、Bind の状態の推移はシンプルに次のようになります

[Not Active] -> [Bind]

束縛したい key の値を知らない、もしくは自分で調べるのがめんどくさいので sansi に任せたい場合、sansi が送ってくる値を確認して問題がなければその値に束縛する場合が 2. の手順になります。遷移は

[Not Active] -> [Bind Waiting] -> [Bind Requesting] ->[Bind]

確認せずに自動的にその環境に束縛するのが 3. の手順になります。遷移は

[Not Active] -> [Auto Bind Waiting] -> [Binding]

related works

こちらを参照いただければ幸いです

名前の由来

Koshinto と Sansi の名前の由来はこちらを参照賜われれば至福の至に存じます次第です

結び

長々と書いてしまい本当にどうもすみません、今は謹んで反省しております次第です、無駄に長生きした年寄りの話が無駄に長いのは相応というものでございますれば、エンジニアの情けで許してくだされ/(^o^)\

references

明日は

明日は@azukisiromochiさんによる「アプリ名『焼き鳥』事件 ???」です!私は前日なのでメンションもらって限定公開の頃から読ませて頂いてたのですが、正直、ものすごくおもしろい、ためになるお話なんですよ!お楽しみに!


  1. もともと RPi だけの、それも SD CARD と Board の ID だけのつもりだったのに、つい NIC を追加したら Mac や Linux 一般にも欲がでて、という途中からの仕様追加を個人開発なのにやりまくったのも悪かったかもしれません 

  2. 無駄に工学博士持ってます。せっかく博士なんだから、何時の日かガッチャマンみたいな自分の戦隊が欲しいと日々思いつつなんか作ってます。わるもんでもいいけど。それか怪盗グルーとミニヨンみたいな仲間とか 

  3. タイトルに反してそういう人達へのネガティブな感情が前提にあるのかと読んでて勘ぐりました 

  4. Raspberry Pi 以外の各種 IoT ボードも Linux ベースであれば IP address や MAC IDに束縛することで利用可能です。ボード固有のIDのへの束縛も対応していきたく、リファレンスボードの donation を募集してます 

  5. Windows は持ってないので、開発に使える PC の donation を募集しています 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

はじめてのnlコマンド

nlコマンドはテキストデータに行番号を付加する機能を持つ、便利なコマンドラインユーティリティです。ほとんどのUnix系環境では、特別なソフトウェアをインストールをすることなく最初から使うことができるコマンドです。この記事では、はじめてnlを触る人でも気軽に試せるよう基本的な使い方を説明します。

nlコマンドができること

nlができることは「テキストデータに行番号をふる」ことです。それ以上でも以下でもありません。コマンドの機能としてはそれだけですが、行番号をふることに関して様々な要求を満たすためのオプションを持っています。そして他のコマンドと組み合わせることで、その用途は「行番号をふる」という枠を越えて広がっていきます。

nlコマンドの使い方

基本的な使い方

例えば、JR上野東京ライン北行(宇都宮線・高崎線)の駅名が記載された「utl-kita」という名前のテキストファイルがあるとします。ファイルの中身をそのまま標準出力に表示するcatを使うと次のようになります。

$ cat utl-kita 
東京
上野
尾久
赤羽
浦和
さいたま新都心
大宮

このテキストファイル「utl-kita」にnlを使用した場合、以下のような出力になります。

$ nl utl-kita 
     1  東京
     2  上野
     3  尾久
     4  赤羽
     5  浦和
     6  さいたま新都心
     7  大宮

これでnlによって行の先頭に行番号が付加されたことが確認できたと思います。

標準入出力の利用

引数を指定してファイルから読み込む以外にも、標準入力から直接データを受け取ることができます。また、標準入力から受け取ることをより明示的にするために、-という特殊な引数も用意されています。標準入出力と|(パイプ)を利用することで、様々なコマンドを組み合わせることができます。

さきほどの例は、catnlを組み合わせて以下のように実行しても同じ結果になります。

$ cat utl-kita | nl
     1  東京
     2  上野
     3  尾久
     4  赤羽
     5  浦和
     6  さいたま新都心
     7  大宮

パイプを使えばいくつでもコマンドをつなげることができます。以下の例では、yesによって出力される「y」にnlが行番号を付加し、headが先頭3行だけを切り取って標準出力に表示しています。

$ yes | nl | head -n 3
     1  y
     2  y
     3  y

リダイレクトとファイル

行番号を付加したデータをファイルに保存するには、>(リダイレクト)を使って出力するファイルを指定します。

$ nl utl-kita > numbered_utl-kita
$ cat numbered_utl-kita
     1  東京
     2  上野
     3  尾久
     4  赤羽
     5  浦和
     6  さいたま新都心
     7  大宮

これでファイルに保存することができました。残念ながらリダイレクトで元のファイルへの上書き保存はできません。ファイルが消失するので、試す場合は覚悟を持って試しましょう。

$ nl utl-kita > utl-kita
$ cat utl-kita
$ wc utl-kita
0 0 0 utl-kita

リダイレクトで読み込むファイルと同じファイルに出力した結果、データが消失していることがわかります。wcは文字数をカウントするコマンドで、出力の3つの0 0 0は、左から行数、単語数、バイト数を表します。参考までに元のテキストファイルに対してwcを実行したときの結果は以下になります。

$ wc utl-kita 
 7  7 64 utl-kita
$ wc numbered_utl-kita 
  7  14 113 numbered_utl-kita

詳しくは説明しませんが、上書き保存をするにはmoreutilsというコマンドユーティリティに含まれるspongeコマンドを利用する方法などがあります。


補足

サンプルのutl-kitaファイルは、以下のテキストをプロンプトに貼り付ければ簡単に作成することができます。

cat <<EOF >utl-kita
東京
上野
尾久
赤羽
浦和
さいたま新都心
大宮
EOF
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Postfixメモ

deferredキューに滞留しているメールが再送を何日で諦めるかはこの設定値で決まる。
以下は5日の場合

$ postconf | grep -i lifetime
bounce_queue_lifetime = 5d
maximal_queue_lifetime = 5d
滞留メールを見る
# postqueue -p

個別にメールをHOLDする
# postsuper -h キューID

HOLD中のメールをキューに入れ直す(キューIDが変わる)
# postsuper -r キューID

HOLDキューにあるメールを全て再送する
# postsuper -H ALL
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

tshark: The file to which the capture would be saved ( filename ) could not be opened: Permission denied. の対応法

実現したいこと

[vagrant@localhost ~]$ pwd
/home/vagrant
[vagrant@localhost ~]$ id
uid=501(vagrant) gid=501(vagrant) groups=501(vagrant),10(wheel)
[vagrant@localhost ~]$ 
[vagrant@localhost ~]$ sudo tshark -i enp0s8 -w testcap_`date +%Y-%m-%d_%H-%M-%S`.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s8'
tshark: The file to which the capture would be saved ("testcap_2020-11-30_01-56-22.pcap") could not be opened: Permission denied.

[vagrant@localhost ~]$ 
[vagrant@localhost ~]$ 
[vagrant@localhost ~]$ sudo su -
最終ログイン: 2020/11/30 (月) 01:52:42 JST日時 pts/1
[root@localhost ~]# 
[root@localhost ~]# pwd
/root
[root@localhost ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@localhost ~]# 
[root@localhost ~]#  sudo tshark -i enp0s8 -w testcap_`date +%Y-%m-%d_%H-%M-%S`.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s8'
tshark: The file to which the capture would be saved ("testcap_2020-11-30_01-56-38.pcap") could not be opened: Permission denied.

[root@localhost ~]# 
[root@localhost ~]# getenforce 
Disabled
[root@localhost ~]# 

root権限で実行しているのに上記のようにエラーが出てパケットキャプチャした結果をファイルに保存できない。パケットキャプチャー結果をファイルに保存したい。

実行コマンド

$ sudo mkdir -p /opt/capfile
$ sudo tshark -i enp0s8 -w /opt/capfile/testcap_`date +%Y-%m-%d_%H-%M-%S`.pcap

/rootディレクトリ および /homeディレクトリ(登録されているユーザー) 以外に作成する

補足

  • 忘れるからメモ

情報源

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

wiresharkで特定のHTTP Request Method(例えばGET、POST)のみ表示する

実現したいこと

wiresharkのFilter機能で特定のHTTP Request methodのみを表示させたい。
例えば、POSTのみを表示させたいだったり、GETリクエストのみを表示させたい場合に利用する。

実行コマンド

HTTPリクエストメソッド GETの場合

http.request.method == "GET"

Filterツールバーに上記のように入力する

image.png

HTTPリクエストメソッド POSTの場合

http.request.method == "POST"

Filterツールバーに上記のように入力する

image.png

補足

HTTPリクエストメソッド GETで特定のパラメータのみ表示する場合

image.png

http.request.uri == "/?num=5"

Filterツールバーに上記のように入力する

image.png

使い所(個人用のメモです...)

  • デバッグ用途に使っています。フロントのHTTPサーバーからアプリケーションサーバー(例えばwsgiサーバーなど)へのリクエストを確認する。

情報源

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む