- 投稿日:2020-05-28T21:30:43+09:00
Developing Cipher Algorithms(1/2)
https://www.kernel.org/doc/html/latest/crypto/devel-algos.html
Docs » Linux Kernel Crypto API » Developing Cipher Algorithms
Developing Cipher Algorithms
Registering And Unregistering Transformation
There are three distinct types of registration functions in the Crypto API. One is used to register a generic cryptographic transformation, while the other two are specific to HASH transformations and COMPRESSion. We will discuss the latter two in a separate chapter, here we will only look at the generic ones.
Crypt APIには、3つの異なる種類の登録関数があります。1つは、一般的な cryptographic transformationを登録するもので、残り二つは、HASH trasnfomationとCOMPRESSionです。最後の2つについては別の機会に議論するとして、ここでは本来の一般的な最初についてだけ見ていきます。
Before discussing the register functions, the data structure to be filled with each, struct crypto_alg, must be considered – see below for a description of this data structure.
登録関数について議論する前に、それぞれ埋めるべきデータ構造体、struct crypt_alg について考えなければなりません。このデータ構造の詳細は以下を確認してください。
The generic registration functions can be found in include/linux/crypto.h and their definition can be seen below. The former function registers a single transformation, while the latter works on an array of transformation descriptions. The latter is useful when registering transformations in bulk, for example when a driver implements multiple transformations.
一般的な登録関数は、include/linux/crypto.hで見つけることができ、それらの定義は以下で見ることができます。former functionはsingle transformationを登録します、後者はtransfomation descriptorsの配列を登録します。。後者は、transformationをまとめて登録するときに役に立ちます。例えば、ドライバーには複数のtransfomationが実装されている場合です。
int crypto_register_alg(struct crypto_alg *alg); int crypto_register_algs(struct crypto_alg *algs, int count);The counterparts to those functions are listed below.
これらの関数に対応するものは、以下になります。
void crypto_unregister_alg(struct crypto_alg *alg); void crypto_unregister_algs(struct crypto_alg *algs, int count);The registration functions return 0 on success, or a negative errno value on failure. crypto_register_algs() succeeds only if it successfully registered all the given algorithms; if it fails partway through, then any changes are rolled back.
登録関数は成功したら0を、失敗したら負のerrno valueを返します。crypto_register_algs()では、全ての与えられたアルゴリズムに対して、登録が成功した場合にのみ成功となります。途中で失敗した場合には、変更はすべてロールバックされます。
The unregistration functions always succeed, so they don’t have a return value. Don’t try to unregister algorithms that aren’t currently registered.
登録解除関数は常に成功し、戻り値はありません。現在登録していないアルゴリズムに対して、登録解除を試みないでください。
Single-Block Symmetric Ciphers [CIPHER]
Example of transformations: aes, serpent, …
This section describes the simplest of all transformation implementations, that being the CIPHER type used for symmetric ciphers. The CIPHER type is used for transformations which operate on exactly one block at a time and there are no dependencies between blocks at all.
このセクションでは、全てのtransfomation実装のなかでもっとも単純である、symmtric ciphersを用いたCIPHER typeについて記述します。CIPHER typeは、一度に唯一の1ブロックのみを操作し、ブロック間に依存性の無いときに使われます。
Registration specifics
The registration of [CIPHER] algorithm is specific in that struct crypto_alg field .cra_type is empty. The .cra_u.cipher has to be filled in with proper callbacks to implement this transformation.
[CIPHER] algorithmの登録は、構造体crypto_alg のfirld .cra_typeが空である特徴を持ちます。このtransofrmを実装するには、cra_u.cipherに適切なコールバックを入力しなければなりません。
See struct cipher_alg below.
Cipher Definition With struct cipher_alg
Struct cipher_alg defines a single block cipher.
構造体cipher_algは、single block cipherを定義します。
Here are schematics of how these functions are called when operated from other part of the kernel. Note that the .cia_setkey() call might happen before or after any of these schematics happen, but must not happen during any of these are in-flight.
以下は、kernelのほかの部分から処理されたときに、これらの関数がどのように呼び出されるのかを示す図である。cia_setkey()は、これらの処理が実行される前か後に呼び出され、決して実行中には呼ばれないことに注意してください。
KEY ---. PLAINTEXT ---. v v .cia_setkey() -> .cia_encrypt() | '-----> CIPHERTEXTPlease note that a pattern where .cia_setkey() is called multiple times is also valid:
cia_setkey()が複数回呼ばれるパターンも有効であることを注意してください。
KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --. v v v v .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt() | | '---> CIPHERTEXT1 '---> CIPHERTEXT2Multi-Block Ciphers
Example of transformations: cbc(aes), chacha20, …
This section describes the multi-block cipher transformation implementations. The multi-block ciphers are used for transformations which operate on scatterlists of data supplied to the transformation functions. They output the result into a scatterlist of data as well.
このセクションでは、multi-block cipher transformの実装について記述します。multi-block cipherは、transfomation functionに提供されるデータのscatterlistを操作するtransformに使用されています。また結果をデータのscatterlistの中に出力します。
Registration Specifics
The registration of multi-block cipher algorithms is one of the most standard procedures throughout the crypto API.
multi-block cipher algorimの登録は、crypto APIを通過する最も基本的なやり方の1つである。
Note, if a cipher implementation requires a proper alignment of data, the caller should use the functions of crypto_skcipher_alignmask() to identify a memory alignment mask. The kernel crypto API is able to process requests that are unaligned. This implies, however, additional overhead as the kernel crypto API needs to perform the realignment of the data which may imply moving of data.
cipher実装は、dataの適切なアライメントを期待していることに注意してください。呼び出し元は、crypto_skcipher_alignmask()の関数を使って、メモリアライメントマスクを扱わねばなりません。kernel crypyo APIは、alignmentがあっていない要求を実行することができます。ただし、カーネル暗号APIがデータの再調整を実行する必要があるため、データの移動を意味する可能性があるため、これは追加のオーバーヘッドを意味します。
Cipher Definition With struct skcipher_alg
Struct skcipher_alg defines a multi-block cipher, or more generally, a length-preserving symmetric cipher algorithm.
構造体 skcipher_algでは、multi-block cipher、より一般的に言えば、長さ維持する対象cipher algorithmを定義します。
Scatterlist handling
Some drivers will want to use the Generic ScatterWalk in case the hardware needs to be fed separate chunks of the scatterlist which contains the plaintext and will contain the ciphertext. Please refer to the ScatterWalk interface offered by the Linux kernel scatter / gather list implementation.
ハードウェアに平文と暗号文を含むscatterlistの個別のチャンクを供給する必要がある場合に備えて、一部のドライバはGeneric ScatterWalkを使用することを望みます。
- 投稿日:2020-05-28T20:16:48+09:00
Linux基礎11 -テキスト処理-
はじめに
Linuxではアプリケーションのデータやシステムの設定項目などの多くがテキストとして表現されています。そのためこれらのテキストを扱うことがLinuxでの主な作業になります。今回はテキスト処理を効率よく行うために、便利なコマンドを紹介します。
wcコマンド
wcコマンド
は入力ファイルの行数・単語数・バイト数を数えるコマンドです。wcコマンド$ wc /etc/passwd => 21 31 973 /etc/passwd #オプションを指定しない場合、左から行数(21)、単語数(31)、バイト数(973)を示す
-l
、-w
、-c
オプションを指定するとそれぞれ行数
、単語数
、バイト数
だけを表示します。
中でも-l
オプションは利用頻度が高いです。例えば、ルートディレクトリ直下にあるファイルやディレクトリの数を調べられます。
なお、今回紹介するコマンドは、ファイル名を指定しない場合、標準入力をから読み込む
ことを念頭に入れておいてください。
標準入力についてはLinux基礎10 -標準入出力とパイプライン-を参照してください。フィルタを使う際に標準入力から読み込むことを明示的に指定したい場合には
-(ハイフン)
を入力ファイル名として利用します。標準入力を明示的に指定する$ ls / | wc -l - => 20 -sortコマンド
sortコマンド
は行単位でテキストをソートするコマンドです。ソートとは、一定の規則に基づいて行を並べ替えることです。ASCIIコード順にソート
sortコマンド
は、デフォルトではACSIIコード
順に行を並べ替えます。ASCIIコード
とは、コンピュータ上で文字を表現するためのコード体系の1つです。コンピュータの内部では、アルファベットや、数字、記号などの半角英数字には、1つ1つの番号が振られており、この番号のことをASCIIコード
呼びます。歴史的な理由から、ASCIIコードは、大文字の方が番号が小さく、小文字の方が割り当てられているため、sortコマンド
用いた場合は、大文字が先に並べられることに注意しましょう。では、例として次の内容のファイルを並べ替えてみましょう。
このファイルをsortコマンド
でソートすると、次のようにアルファベット順に並べ替えられます。
sortコマンド
行の先頭から文字を比較していきますが、行の途中の特定の項目を対象としてソートすることもできます。次の例をみていきましょう。
ps xコマンド
の結果は、PID
の順に表示されます。出力結果は、それぞれの項目がスペース区切りとなっており、この各項目をフィールド
と呼びます。上の例でいうと、第一フィールドがPID、第二フィールドがTTYですね。
ここでCOMMAND
フィールドを対象として、行を並べ替えたいとしましょう。ソートするフィールドは-k
オプションを指定して、フィールド番号を引数に指定します。今回の場合は-k 5
を指定します。
COMMAND
のフィールドを対象にASCIIコード順にソートすることができました。数値順にソート(-n)
-n
オプションは、文字列を数値とみなして並べ替えるためのオプション
です。例として次のようなテキストファイルを考えてみましょう。
このファイルを、オプションを指定せずにsortコマンド
を実行すると次のような結果になります。
これは、sortコマンド
が各行を文字列として評価しているためです。各行の値を数値として評価するために-n
オプションを指定してあげると次のように変化します。
逆順にソート(-r)
sortコマンド
の-r
は逆順にソートするためのオプションです。デフォルトでは昇順
にソートされますが、-r
をつけると降順
でソートしてくれます。
応用として、数値データが記録されたファイルなどを値の大きい順に並べ替える
ことができます。例としてlsコマンドの結果をファイルサイズの大きい順に並べ替えてみましょう。headコマンド
を組みわせて、上位5つを取得するようにしています。
uniqコマンド
uniqコマンド
は連続した
同じ内容の行を省くコマンドです。次の例をみていきましょう。
file3では、HokkaidoやIwateが連続して重複していましたが、uniqコマンド
を実行することで、重複を省くことができました。注意点としては、uniqコマンド
は、同じ内容の行が連続している場合にのみ重複を取り除くことができる
ということです。
次の例をみていきましょう。
連続して
存在していたAomoriの重複は省かれましたが、離れて
存在していたHokkaidoは残っています。全体から重複行を取り除きたい場合には、一旦sortコマンド
で並び替えてからuniqコマンド
を実行することで、可能になります。
重複行を数える
uniqコマンド
には様々なオプションがありますが、その中でもよく使われる-c
オプションを紹介します。-c
オプションは重複している行数を数えて表示するためのオプションです。例えば対象のファイルに各データがそれぞれ何件あるかを調べたりする時に使います。先ほどのfile4でに使ってみましょう。
cutコマンド
cutコマンド
は入力行の一部分を切り出して、出力するコマンドです。cutコマンド$ cut -d <区切り文字> -f <フィールド番号> [<ファイル名>] #区切り文字を指定しない場合はtabが区切り文字とみなされる $ cut -d , -f 3 file.csv #入力例 区切り文字を(,)とみなして、3番目のフィールドだけが表示される例として、
/etc/passwd
ファイルを対象にします。
/etc/passwd
ファイルは「:」で区切られて、それぞれのフィールドが形成されています。それぞれのフィールドは次の表のような意味を持っています。
フィールド番号 意味 1 ユーザ名 2 パスワード(本物ではなくダミー) 3 ユーザID 4 グループID 5 コメント(本名など) 6 ホームディレクトリ 7 ログインシェル trコマンド
trコマンド
は文字を置き換えるコマンドです。trコマンド$ tr <置換前の文字> <置換後の文字> $ tr : , #(:)を(,)に置換する例今回は先ほどの
/etc/passwd
ファイルを対象に「:」を「,」に置き換えてみましょう。
複数の文字を置換することもできます。a->A、b->B、c->C
に変更してみましょう。
注意すべきは、abc
という文字列を対象としているのではなく、a
、b
、c
という単独の文字を置き換えているということです。置換文字に-(ハイフン)を利用することで、文字範囲を指定することができます。例えば
a-z
と書くと、abcdef...xyz
と同じ意味になります。
おさらいですが、trコマンドは1文字単位の文字置換です
ので注意しましょう。文字列の置換を行いたい場合は、sedコマンド
やawkコマンド
を利用します。これは後の記事で後述します。ファイル指定の注意
trコマンド
は、純粋なフィルタとして設計されており、ファイルから直接読み込むことはできません
。
テキストファイルにtrコマンド
指定したい場合はcatしてパイプ
をわたすか、もしくは入力リダイレクト
を使用してください。テキストファイルへのtrコマンドの使用$ cat /etc/passwd | tr : , #パイプを使う場合 $ tr : , < /etc/passwd #入力リダイレクトを使う場合文字の削除
trコマンド
を使用すると文字を削除
することができます。trコマンドによる文字の削除$ tr -d <削除文字列>tailコマンド
tailコマンド
はファイルの末尾を表示するコマンドです。オプションを指定しない場合は、次のようにファイルの末尾10行が表示されます。
tailコマンド
で表示する行数は、-n
オプションで指定します。ファイルへの追記を監視する
ログの出力やデータ収集などで、常時追記されていくファイルを表示する際に、追記されるたびにその内容を表示してファイルを監視したい場合があります。そのような場合は
-f
オプションを指定します。tail_-fでファイルを監視$ tail -f <ファイル名>これにより、ファイルの内容が書き換えられると、
リアルタイム
に表示されます。下の例ではターミナルを2つ起動して、片方でtail -f
を実行しながら、もう1つのターミナルでファイルへ書き込みを行っています。
diffコマンド
diffコマンド
は2つのファイルの差分を表示するコマンドです。このコマンドはプログラムのソースコードの編集前と編集後を比較するのによく使用されます。diffコマンド$ diff [オプション] <比較元ファイル> <比較先ファイル>ここでは例として、file1をコピーしてfile1cpを作成し、末尾に都道府県を追加しました。
diffコマンド
で変更前後を比較してみましょう。
7a8,11
の部分は変更コマンド
と呼ばれる部分で、以下の表の通りの意味を持ちます。
記号 内容 <範囲>a<範囲> Addのa。1つ目のファイルの範囲1の後に、2つ目のファイルの範囲の内容が追加された <範囲>c<範囲> Changeのc。1つ目のファイルの範囲1の箇所が、2つ目のファイルの範囲2の内容に変更された <範囲>d<範囲> Deleteのd。1つ目のファイルの範囲1の箇所が削除された 今回は、
7a8,11
なので、変更前のファイルの7行目の後に変更後のファイルの8-11行目の内容が追加されたということですね。
なお、追加した内容は、変更コマンドの下に記述されますが、ここでの>
や<
はそれぞれ次の意味を持ちます。
記号 内容 < 1つ目のファイルにだけ存在する行 > 2つ目のファイルにだけ存在する行 今回は、"Tochigi"から"Saitama"が編集後のファイルに追加されていますよという意味ですね。
ユニファイド出力形式
diffコマンド
の差分表示には、ざまざまな形式が、用意されています。デフォルトでは先ほどの>
や<
で表現されていますが、よく使われる形式として、ユニファイド形式(Unified format)
があります。ユニファイド形式は、diff -u
で出力できます。先ほどの都道府県の変更例をユニファイド形式で出力してみましょう。
ユニファイド形式
の特徴は以下の通りです。
- 最初の2行に2つのファイルのファイル名と更新日時が表示されます
- 3行目からが差分で、
追加した行には+、削除された行には-がつきます
- 差分は変更箇所だけでなく、その前後何行かも合わせて表示されます
- 差分表示の冒頭、@@から始まる行は、その差分が元ファイルの何行目に対応しているのかを示しています。これは「
@@ -<1つ目のファイルの変更開始行>,<変更行数> +<2つ目のファイルの変更開始行>,<変更行数>
」という形式で表されます。<変更行数>は変更のあった行だけでなく、その前後も含みます差分の使い方とパッチ
あるファイルの変更を他人に伝える時に、変更後のファイル全体を送るのではなく、
diffコマンドで出力した分だけ
を共有することもできます。このとき、受信者は元ファイルと差分ファイルから、変更後のファイルを復元できます
。
修正内容を共有するこのようなファイルのことを、パッチ
と呼びます。diffコマンド
で出力した差分はpatchコマンド
でパッチを当てる(修正を適応する)ことができます。パッチを適応する際、元ファイルが変更されていて、行番号がずれていると、エラーとなることがあります。しかし、ユニファイド形式
なら前後の内容も含まれているため、行が多少ずれていても、パッチとして適応できます。
ユニファイド形式
はGitの差分表示にも使われていたりするので、目にする機会が多いでしょう。参考資料
- 投稿日:2020-05-28T16:00:12+09:00
mvコマンド 一つ上の階層に移動
- 投稿日:2020-05-28T15:06:54+09:00
接続制限されたWebサーバでのサイト更新
ユーザー独自で導入されたWebサーバ(OSはRedhatLinux-Ver8)に、Wordpressを
導入し、Webサイトを構築したいとの話が有りました。
Webサーバ自体はセキュリティの観点から、サーバ上へのファイルのアップ、サーバ
サーバ内のファイル等の更新、設定変更等を行う場合、外部からの接続はSSH経由の
接続しか許可されていないとの事です。
この様なサーバ環境でWordpressを導入する場合、Wordpressの管理画面への接続は
どの様に行えば宜しいのでしょうか?
そもそも出来ないと云う事であれば、Wordpressは諦めていただき、ホームページ
作成ソフトを利用するよう、ユーザー様には伝えたいと思っております。よろしくお願い致します。
- 投稿日:2020-05-28T02:19:08+09:00
CentOS7 on VirtualBOXにおけるホストOSとの共有フォルダ設定方法
はじめに
はじめまして。「かびごん」といいます。
普段は、金融機関でビジネスを理解しようとしないデータサイエンティストをしています。
Qiita初記事として自分の奮闘記録を残したいと思います。執筆の背景
UdemyでDockerを勉強を進める際に、VirtualBoxの共有フォルダ設定(ホストOS⇔ゲストOS)が必要になりそこでハマってしまいました。
先駆者の方々の記事はあるものの、どれもそのままでは解決できず、さまざまな情報のアンサンブル学習の末、設定が出来ましたので備忘録も含めこちらに記します。
参照された方の一助となれれば幸いです。※Vagrantを使えば楽だよ!という事は承知の上、どうしても下記環境下での作業が求められていたため奮闘しておりました。
実行環境
(Host OS) Windows10 pro
(Guest OS:virtual)CentOS7.7 (1908) CLI
(Virtualization)VirtualBox 6.1.8-137981
試行時期:2020/05/28手順
CentOS導入~起動までは省きます。
VirtualBoxでは、[設定]>[共有フォルダー]といったいかにも親切そうな設定項目があり、ここでホストOSのフォルダを指定してあげれば出来るんだろうな~と思ったのもつかの間。
VirutalBoxでは共有フォルダーの設定の前に、
「Guest Additions」というものを設定してあげなければいけません。
※これが厄介下記で、一連の流れを説明します。
GetAdditions設定前夜(パッケージ更新)
su
でroot権限に移った後
パッケージのアップデートと必要なパッケージのインストールを実施します。yum -y update yum -y install kernel-devel kernel-headers gcc gcc-c++ yum -y install bzip2
kernel-devel
とkernel-headers
から初めてしまうと、アップデートされていない既存kernelとの整合性がとれなくなってしまうので、kernelのアップデート(yum -y update
に含まれる)を先に実行する意味があります。
bzip2
は後の工程で必要になるので、ここでインストールする事をお勧めします。上記の工程が終了したら一度
reboot
で再起動しましょう!GuestAdditionsのインストール
(再起動後また、
su
コマンドでroot権限に移行しておく)GuestAdditionsはisoイメージ形式で導入しますが、特段入手する必要なく、VirtualBoxに標準で搭載されています。
※搭載されているだけで、それを読み込む必要があります。ISOイメージの挿入
VirtualBoxの[デバイス]>[Guest Additions CDイメージの挿入...]を選択し接続。
※上図赤枠部分インストール
接続したディスクイメージをCentOS内
media
フォルダへマウントします。mount -r /dev/cdrom /media
media
フォルダへ移動し、
マウントの完了後、マウントイメージからインストールを実行します。
ここで行う、VBoxLinuxAdditions.run
の際にbzip2
パッケージが必要となります。cd /media sh ./VBoxLinuxAdditions.runインストールが完了したら、イメージをアンマウントして再起動をする。
cd umount /media reboot共有フォルダの設定
再起動からの復帰後、[デバイス]>[共有フォルダー]>[共有フォルダー設定]から、
ホストOS(今回は、Windows)内の共有したいフォルダを設定します。
[共有フォルダー設定]を選択すると、下記ウィンドウへ遷移します。
「共有フォルダー」を選択し、右側の新規追加ボタンを押します。
任意のフォルダを選択します。(今回はdocker_file
というフォルダ名)
また、
- 自動マウント(A)
- 永続化する(M)
にチェックをし、[OK]を押して閉じる。
これで、ゲストOS(CentOS)内で
/media/sf_{共有フォルダ名}
今回の場合は、/media/sf_docker_file
として共有される。
※もし、共有されていない場合は再起動をかけてみましょう。共有フォルダのマウント
上記、
/media/sf_{共有フォルダ名}
以外でマウントしたい場合は、su cd media/ mount -t vboxsf sf_{共有フォルダ名} {マウント先のディレクトリ名} rebootで、ゲストOS内で別フォルダを共有フォルダとすることができます。
アクセス制限設定
上記までの作業で、rootユーザーが共有フォルダを利用可能になりますが、その他一般ユーザーに共有フォルダのアクセス権を与える場合は、下記のコマンドでユーザーを追加します。
su gpasswd --add {ユーザ名} vboxsf関連記事
各記事、大変参考にさせて頂き、一部引用させて頂いた部分があります。
もし、ご迷惑なようであればご指摘頂けますと幸いです。
参考サイト
- 投稿日:2020-05-28T01:14:58+09:00
Wake on LAN用のPythonスクリプトを作成する(NAT超えWake on LAN[5])
はじめに
前回の続きです.
とりあえずやりたいことはこんなんです.今回は遂に「Wake on LAN用のPythonスクリプトを作成する」です.
- [1]GCPとMyDNSを使って,ドメインを取得する
- [2]GCPにSoftether Serverを立てる(iPhone/ラズパイから接続)
- [3]GCP上のApacheからローカルのラズパイApacheにリバースプロキシする
- [4]ラズパイをルーター化する
- [5]Wake on LAN用のPythonスクリプトを作成する.
DesktopPCの設定
前提:Ubuntu18.04です.
まずはWake on LANが実行できるように設定します.固定IPの割り当て
sudo vi /etc/netplan/~~.yaml
以下を記入します,
/etc/netplan/~~.yaml# Let NetworkManager manage all devices on this system network: version: 2 renderer: NetworkManager ethernets: eno1: dhcp4: no wakeonlan: true # enable wake on lan addresses: [192.168.1.**/24] # assign arbitrary address gateway4: 192.168.1.1 # your router(raspi)'s address nameservers: addresses: [8.8.8.8,8.8.4.4] # google's public dns再起動します.
sudo netplan apply sudo rebootwake on lan が有効になっているか確認するために
ethtool
をインストールします.sudo apt-get install -y ethtoolEthernetの名前をメモします.ついでにIPが固定されているか確認します.
$ ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eno1<<<<copy<<<<: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff inet 192.168.1.**/24 brd 192.168.1.255 scope global noprefixroute eno1 valid_lft forever preferred_lft forever inet6 fe80::2d8:61ff:fe56:242d/64 scope link valid_lft forever preferred_lft foreverWake on LANが有効になっているか確認します.
Wake-on: g
になっていればOKです.$ sudo ethtool eno1 ~~ Supports Wake-on: pumbg Wake-on: g # if it's d, your wake on lan setting may be wrong ~~BIOSの設定
省略します.起動される側のPCのWOL設定(1/3):BIOS/UEFIの設定wo
参考にしてください.確認
ラズパイで
ip a
を確認してDesktopに繋いでいるEthernetにipが割り当てられていればOKです.(UP,LOWER_UP
になっている必要があります.ありがとうtelcomM)$ ip a 4: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff inet 192.168.1.1/24 brd 192.168.1.255 scope global noprefixroute eth1 valid_lft forever preferred_lft forever inet6 fe80::83fa:6dee:9799:9a6e/64 scope link valid_lft forever preferred_lft forever確認(wakeonlanをインストールし起動できるか確認)
ラズパイにwakeonlanをインストールします.
sudo apt install wakeonlanwakeonlan -i 192.168.1.255 -p 7 **:**:**:**:**:**これで起動できればOKです.
mod_wsgi
まず,PythonスクリプトをApacheで動かすことができる
mod_wsgi
と諸々をインストールします.sudo apt install python3-dev python3-pip apache2 libapache2-mod-wsgi-py3 sudo apt-get -y install python3 ipython3 python3-flask curlPythonスクリプト作成
とりあえず動くPythonスクリプトを作成します.今回はFlaskを用います.
cd ~ mkdir flask && cd flask vi app.py~/flask/app.pyfrom flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'This is vpn server for wake on lan!\n\n' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)とりあえず,mod_wsgiが動くか確認します.
$ python3 app.py $ curl http://localhost:5000 # 別タブで This is vpn server for wake on lan!”This is vpn server for wake on lan!”と出ればOKです.
Apacheとmod_wsgiの設定
新たにflask用の設定ファイルを作成します.
sudo vi /etc/apache2/sites-available/flask.conf
今回はGCPから80ポートにリダイレクトされるようにしているので以下のように記入します.
/etc/apache2/sites-available/flask.conf<VirtualHost *:80> ServerName kado.example.com WSGIDaemonProcess flask user={username} group={username} threads=5 WSGIScriptAlias / /home/{username}/flask/adapter.wsgi <Directory /home/{username}/flask/> WSGIProcessGroup flask WSGIApplicationGroup %{GLOBAL} WSGIScriptReloading On Require all granted </Directory> </VirtualHost>
flask.conf
を有効化します.sudo a2dissite 000-default.conf sudo a2ensite flask.conf sudo service apache2 restartadapter.wsgiファイルを作成します.
vi ~/flask/adapter.wsgi~/flask/adapter.wsgiimport sys if sys.version_info[0]<3: # require python3 raise Exception("Python3 required! Current (wrong) version: '%s'" % sys.version_info) sys.path.insert(0, '/home/kadorpi/flask/') from app import app as application # <- app means app of app.pyApacheを再起動します.
sudo service apache2 restart
動いているか確認します.
$ curl localhost This is vpn server for wake on lan!これで,PythonスクリプトがApache上で動くようになりました.
Line bot用のWake on LANスクリプト作成
ここまできたら後少しです.LineからGCPにHTTPリクエストを送り,受け取ったリクエストをラズパイの80ポートにリダイレクトします.そして,ラズパイで受け取ったリクエストをPythonで処理します.
まず,Line Developerにアカウントを登録します.
次にChannelを作成します.Channel Secretを発行し,メモします.
Channel Access Tokenを発行し,メモします.
>Response settingsからAuto-replyなどを適宜設定します.
>Message APIからWebhookURLを入力します.今回は
https://{domain name}/wake-on-lan
とします.これでLINE Botの設定は終わりです.
mod_wsgiの再設定
環境変数として,先ほどメモしたChannel SecretとChannel Access Tokenを設定します.
vi ~/flask/adapter.wsgi以下を追記します.
~/flask/adapter.wsgiimport os os.environ['LINE_CHANNEL_SECRET'] = 'fuga' os.environ['LINE_CHANNEL_ACCESS_TOKEN'] = 'hogehoge'Pythonスクリプト
必要なモジュールをインストールします.
pip3 install line-bot-sdk flask
pythonコードは以下のようにします.
import os, sys from flask import Flask, request, abort app = Flask(__name__) from linebot import ( LineBotApi, WebhookHandler ) from linebot.exceptions import ( InvalidSignatureError ) from linebot.models import ( TextMessage, TextSendMessage, MessageEvent ) # get channel_secret and channel_access_token from your environment variable channel_secret = os.getenv('LINE_CHANNEL_SECRET', None) channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None) if channel_secret is None: print('Specify LINE_CHANNEL_SECRET as environment variable.') sys.exit(1) if channel_access_token is None: print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.') sys.exit(1) line_bot_api = LineBotApi(channel_access_token) handler = WebhookHandler(channel_secret) @app.route('/') def show_web(): return 'This is vpn server for wake on lan!\n\n' @app.route('/wake-on-lan', methods=['POST']) def wake_on_lan(): # get X-Line-Signature header value signature = request.headers['X-Line-Signature'] # get request body as text body = request.get_data(as_text=True) app.logger.info("Request body: " + body) # handle webhook body try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'ok' @handler.add(MessageEvent, message=TextMessage) def handle_message(event): message = event.message.text replies = [] if re.compile("\s*(check)\s*", re.IGNORECASE).search(message): result = confirm() replies += [TextSendMessage(result)] elif re.compile("\s*(kick)\s*", re.IGNORECASE).search(message): if confirm() == 'Awake': replies += [TextSendMessage('Already awake')] else: result = kick() replies += [TextSendMessage(result)] buttons_template = ButtonsTemplate( title='usage', text='Tap below buttons', actions=[ MessageAction(label=m, text=m) for m in message_list ]) template_message = TemplateSendMessage(alt_text='Usage', template=buttons_template) replies += [template_message] line_bot_api.reply_message(event.reply_token, replies) def confirm(): hostname = "192.168.1.**" response = os.system("ping -c 1 " + hostname) # and then check the response... if response == 0: pingstatus = "Awake" else: pingstatus = "Sleeping" return pingstatus def kick(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(b'\xFF' * 6 + b'\x**\x**\x**\x**\x**\x**' * 16, ('192.168.1.255', 7)) s.close() return 'kicked' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)少し説明を入れると,まず以下でLINE用のChannel SecretとChannel Access Tokenを読み込みます.
# get channel_secret and channel_access_token from your environment variable channel_secret = os.getenv('LINE_CHANNEL_SECRET', None) channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None) if channel_secret is None: print('Specify LINE_CHANNEL_SECRET as environment variable.') sys.exit(1) if channel_access_token is None: print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.') sys.exit(1) line_bot_api = LineBotApi(channel_access_token) handler = WebhookHandler(channel_secret)以下は,Web表示用に一応加えました.
@app.route('/') def show_web(): return 'This is vpn server for wake on lan!\n\n'ここに上記で設定したWebhookのリクエスト処理を書きます.
@app.route('/wake-on-lan', methods=['POST']) def wake_on_lan(): # get X-Line-Signature header value signature = request.headers['X-Line-Signature'] # get request body as text body = request.get_data(as_text=True) app.logger.info("Request body: " + body) # handle webhook body try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'ok'そして,最後にメッセージで"kick"が来たら,MagicPacketの送信,"check"が来たらPingで起動できているかを確認する処理をここで書いています.
@handler.add(MessageEvent, message=TextMessage) def handle_message(event): message = event.message.text replies = [] if re.compile("\s*(check)\s*", re.IGNORECASE).search(message): result = confirm() replies += [TextSendMessage(result)] elif re.compile("\s*(kick)\s*", re.IGNORECASE).search(message): if confirm() == 'Awake': replies += [TextSendMessage('Already awake')] else: result = kick() replies += [TextSendMessage(result)] buttons_template = ButtonsTemplate( title='usage', text='Tap below buttons', actions=[ MessageAction(label=m, text=m) for m in message_list ]) template_message = TemplateSendMessage(alt_text='Usage', template=buttons_template) replies += [template_message] line_bot_api.reply_message(event.reply_token, replies) def confirm(): hostname = "192.168.1.**" response = os.system("ping -c 1 " + hostname) # and then check the response... if response == 0: pingstatus = "Awake" else: pingstatus = "Sleeping" return pingstatus def kick(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(b'\xFF' * 6 + b'\x**\x**\x**\x**\x**\x**' * 16, ('192.168.1.255', 7)) s.close() return 'kicked'Apacheを再起動します.
sudo service apache2 restart
おわり
後半,疲れてだれてしまいました...
さらに備忘録的に書いているのでわかりづらいかもしれません...
とりあえず全部書けたので良かったです。参考になれば幸いです.参考
How To Use Apache HTTP Server As Reverse-Proxy Using mod_proxy Extension
- 投稿日:2020-05-28T00:02:08+09:00
ラズパイをルーター化する(NAT超えWake on LAN[4])
はじめに
前回の続きです.
とりあえずやりたいことはこんなんです.今回は「ラズパイをルーター化する」です.
- [1]GCPとMyDNSを使って,ドメインを取得する
- [2]GCPにSoftether Serverを立てる(iPhone/ラズパイから接続)
- [3]GCP上のApacheからローカルのラズパイApacheにリバースプロキシする
- [4]ラズパイをルーター化する
- [5]Wake on LAN用のPythonスクリプトを作成する.
有線LANアダプタを買う
ラズパイには,LANポートは1つしかないので,有線LANアダプタを書います.こんなやつ.
新しいEthernetに固定IPアドレスを割り当てる
ip a
コマンド(sudo ifconfig
)で確認すると新たなEthernet Ineterfaceが追加されているはずです.今回はeth1
という名前でした.$ sudo ifconfig # ip a の方がいいっぽいです eth1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether 04:ab:18:3b:af:e2 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0固定IPを割り当てます.今回は,下図のようにラズパイをルーター※として,新たなネットワーク(
192.168.1.0/24
)を作りたいので,sudo vi /etc/dhcpcd.conf
以下を追記します.
/etc/dhcpcd.conf# External ethernet interface eth1 static ip_address=192.168.1.1/24 # you can assign arbitrary ip address and subnet mask. Note that client must designate this address as gateway static routers=**.**.**.** # you can assign arbitrary ip too. if this server's network is from another router, set routers address may be better.(you will not need to set dns masquerade) static domain_name_servers=8.8.8.8 # see above line's comment※ルーター化と言っていましたが,実はIPマスカレードするだけでした.
↑の**.**.**.**
にルーターのアドレス,dnsアドレスにGoogleのPublicアドレスを入れています.(もはやルーターではないかもしれませんね...詳しくないのでわかりません笑)
※ラズパイに完全にルーター機能を付与する場合は**.**.**.**
にも任意のアドレスを割り当て,dnsアドレスはコメントアウトすべき?.そして,参考にあるようにDNSマスカレードとDHCPサーバーの設定を行うといいのですかね...確認
ラズパイに繋いだデスクトップPCの電源を入れて,ipを確認すると,
eth1
にIPが割り当てられます.
※デスクトップPCはまだインターネットに繋がりません.sudo ifconfig # or ip a # eth1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 # inet 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 # ether **:**:**:**:**:** txqueuelen 1000 (Ethernet) # RX packets 0 bytes 0 (0.0 B) # RX errors 0 dropped 0 overruns 0 frame 0 # TX packets 0 bytes 0 (0.0 B) # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ping 192.168.1.**IPマスカレードの設定
IPマスカレードの設定をします.
1行目:プライベートIPアドレス空間から-oへの転送許可.
2行目:SNAT.
3行目:DNAT.sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE sudo iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT # SNAT sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT # DNATこのままだと一時的で,再起動すると情報が消えてしまうので,
mkdir ~/iptable && cd ~/iptable sudo iptables-save > iptables.dat sudo vi /etc/rc.local/etc/rc.local# iptables iptables-restore < /home/{user name}/iptable/iptables.datこれで,デスクトップPCがインターネットに繋がるはずです.
参考
Ubuntu 16.04 でルータつくる
Ubuntu 18.04LTS で NAT ルータを構築
Linuxマシンをルータにする方法
手元のUbuntuにUSB-LANアダプタを追加してルータ化する
Ubuntu PCをルータ代わりにして、新しくLANを構築してみる
How to Setup a Raspberry Pi DNS Server
Raspberry PiにDnsmasqをインストールする