- 投稿日:2020-07-08T21:34:19+09:00
Flatpakアプリケーションで日本語入力ができない? 原因は、Fcitx。
私の今の環境は、Lubuntu 18.04である。
Flatpakは、GNU/Linux環境用のパッケージマネージャである。ソフトウェアをサンドボックス内で実行できることから、開発者は、個別のディストロ用に別々のパッケージを作る必要がないため、UbuntuやDebianで、aptを使ってインストールするより、最新版のソフトウェアを取得できる場合が多いのだ。
しかしながら、Flatpakを利用したソフトの多くで、日本語入力ができない現象に見舞われた。あとからというわけではなく、Flatpakアプリをインストールして、最初からである。
原因は、Fcitx
原因は、Fcitxであった。
どうやら、Fcitxの持つ仕組みと、Flatpakのサンドボックス特性が、相性が良くないらしい。簡単な解決法 : IBusに切り替えよう。
Fcitxでダメなら、IBusではどうだろうか。IBusに切り替えたところ...なんと正常に使えるようになった。よって、FcitxからFcitxに乗り換える手順を説明する。
IBus (と、それ用のMozc)のインストール
sudo apt install ibus ibus-mozcインプットメソッドの設定
まず、インプットメソットの設定を開く。端末を開き
im-configすると、以下のようなウィンドウが開く
OKを押して進もう。すると
推奨はされていないが、とりあえず、Yesを選択。
こうなるので、ibusを選択してOK
最後に、こうなる。これで、基本設定は完了だ。適用するには、一旦ログアウトして、再度ログインすれば良い。再ログインしたら
ログインすると、右下のバーに、キーボードのアイコンが現れているので、それを右クリック。そして、設定を開く。
設定画面になるので、「入力メソッド」タブに移動。「追加」を押して、一応、「日本語」キーボードを追加する。そして、英語キーボードを削除。そして、とりあえず、テキストエディタでも開いて、入力しようとしてみよう。しかし...私の場合、英語配列のままだった。
この場合一旦ログアウトして、再度ログインすれば、ちゃんと日本語配列になっていた。半角/全角を押せば、日本語入力もできる。最後に
これで、Flatpakアプリにおいても、日本語入力が可能になった。
- 投稿日:2020-07-08T21:20:00+09:00
conda環境へのパッケージインストールにおける注意点
概要
皆様,こんにちは.
私事で恐縮ですが,最近は忙しく論文執筆に追われておりました.
忙しい時に限って何かとトラブルが起こるものです.今回はそんなトラブル対処の備忘録です.ようやくタスクもひと段落したので,記事としてまとめておきます.
備忘録,メモ的な内容ですので,お気軽に見ていただければと思います.トラブル内容
パッケージがconda環境に入らなかった.以下詳細.
conda環境にパッケージを追加したい.なのでactivateして,
(base) source activate hogehoge (hogehoge) conda install hogehogeしかしcondaのレポジトリにないといわれる.
PackagesNotFoundError: The following packages are not available from current channels:なので,しぶしぶpipでインストールすることに.
(hogehoge) sudo pip install hogehogeしかしなぜかconda環境にパッケージが入らない.
解決法
スーパーユーザ権限で実行してたのが原因.
base環境にぶち込まれてしまう.
なので純粋に,(hogehoge) pip install hogehogeでよい.
スーパーユーザ権限を無心で乱用していたことに対する報いである.
大変しょうもないミスであるが,今後はきちんとコマンド一つにとり何を意味しているかを意識したい.はやく実験しようと焦ると,linuxの基本やコードの記法もおろそかになってくるので,
日頃の自習をしっかりとして,いろんな状況でも対応できるようにしたい.終わりです.ご覧いただきありがとうございました.
- 投稿日:2020-07-08T20:23:21+09:00
sedコマンド
sedコマンド
よくわかっていなかったので簡単にまとめた。
sedコマンドとは
「sed」は「Stream EDitor」の略で
sed -オプション スクリプトコマンド 入力ファイル
以上のコマンドで
指定したファイルをコマンドに従って処理し、標準出力へ出力します。
オプション Right align -r スクリプトで(基本正規表現ではなく)拡張正規表現を使用する -f スクリプトファイル 実行するコマンドとしてスクリプトファイルの内容を追加する -e スクリプト スクリプトを追加する -i 標準出力へ出力する代わりに、出力する内容で元のファイルを置き換える 例
ファイル内の「abc」を「ABC」に変更
sed s/adc/ABC ファイル名
オプションがないとき
最初の引数がsedスクリプトとして、残りの全ての引数は入力ファイルとして扱われる。
/etc/shells の中で、「usr」と書かれている場所を「USER」に置き換える
sed s/user/USER/ /etc/shells #スクリプト #ファイル名簡単にでしたがこんな感じで、
どうゆうものかは理解することができたので、使えるようにしていきたいと思います。
- 投稿日:2020-07-08T18:45:08+09:00
Arch Linuxインストール時の、Wifi接続に関する備忘録
この記事は
Arch Linuxをインストールする際にWifi接続を行う手順を、自分用に簡潔に記録しました。
インストールは基本的に、@TsutomuNakamuraさんの「Arch Linux インストール俺々式完全版」に従って行えば問題なく終わります。
このとき、インターネット接続が必須となるのですが、有線接続が使えなかった自分はWifiの設定にやや苦労したので、その際の解決法を記録しておきます。結論から言うと
WPA/WPA2の場合はwpa_supplicantを使うと良いです。自分はwifi-menuが使えませんでした。
手順
全景
> ip link > ip link set [interface] up > iwlist [interface] scanning | grep "ESSID" > wpa_supplicant -B -i [interface] -c <(wpa_passphrase [ESSID] [password]) > dhcpcd > ping archlinux.org
- [interface] : インターフェースの名前
- [ESSID] : SSID名
- [password] : パスワード
1. インターフェースの名前を確認
ip linkまずはインターフェースの名前を確認する。
Wifiのインターフェースとして、自分の場合は「wlan0」というような名前が表示された。2. インターフェースの有効化(不要なことが多い?)
ip link [interface] up1.で取得したインターフェースが無効になっている場合はこのコマンドで有効化する。インターフェースの有効・無効については、「Arch Linuxインストールメディア環境下でのWi-Fi接続(ワイヤレス設定)について | Unskilled?」の「有効・無効の見分け方」以下を参照。
3. SSIDを検索
iwlist [interface] scanning | grep "ESSID"1.で取得したインターフェースの中から、接続したいWifiのSSIDを探す。見つからない場合は再度コマンドを叩くと表示されることがある他、インターフェースが間違っている可能性がある。
4. Wifiに接続
wpa_supplicant -B -i [interface] -c <(wpa_passphrase [ESSID] [password])1.で取得したインターフェース名、3.で取得したSSID、Wifiのパスワードをそれぞれ入力して接続する。このコマンドはWPA/WPA2が対象のものだが、まあ大概の機器はWPA/WPA2だろうくらいのノリでこの備忘録を書いている。
5. ホスト情報の割り当て
dhcpcd呪文。
IPアドレス等を取得して、各種設定を行う。
詳しくは「dhcpcd - システム管理コマンドの説明 - Linux コマンド集 一覧表」を参照。6. 接続を確認
ping archlinux.org適当なアドレスにpingを打って、接続が完了したことを確認する。
pingの先は適当。まとめ
Arch Linuxって楽しいよね!
- 投稿日:2020-07-08T18:30:28+09:00
Kubernetesにおけるゼロダウンタイムデプロイメント
はじめに
新しいバージョンのアプリケーションをデプロイする時に、アプリケーションをコンテナで運用している場合は、コンテナを作り替える必要がある。デプロイ時に適切な手順を踏まないと、リクエストを正しく捌けずに、クライアントにエラーを返すことになる。これは本番環境で動いているアプリケーションに取ってはクリティカルな問題である。
KubernetesはRollingUpdate
をデフォルトで対応していため、デプロイは適切にManifestを設定をしていればダウンタイムなくデプロイしてくれる。新しいPodの生成からServiceへの追加はヘルスチェック(readnessProbe)を適切に設定するだけで良い。しかし、古いPodを停止する時には、色々考慮する問題が出てくる。適切に設定を行わないと、まだアプリケーションがリクエストを処理中にもかかわらず、Podを停止してしまうということが起こり得る。今回はこの問題を解決するために考察したことをまとめた。KubernetesのPodを停止するまでの挙動
Kubernetesの挙動は以下のようになっている。
Kubernetesでは「
preStop
処理 +SIGTERM
処理」と、「ServiceからのPodの除外処理」が非同期で行われる。コンテナはSIGTERM
のシグナルが送られた場合に、適切に処理中のリクエストを捌き切ってから終了するようにする必要がある。そうでなければ、SIGKILL
シグナルがコンテナに送られて強制終了してしまう。したがって、適切なterminationGracePeriodSeconds
を設定する必要がる。
また、Service
は、該当のコンテナに新しいリクエストを送らないように切り離すが、コンテナが処理を行っている途中である場合は、その接続を切断しないようにしなければいけない。Service (LoadBalancer)
LoadBalancerがコンテナに新しいリクエストを送らないようにするとともに、現在行っている処理の接続を切断しないようにするために、
Connection Draining
の設定をする必要がある。例えば、EKSでは、
Connection Draining
の有効化や、タイムアウトの設定を以下のように設定する。manifestapiVersion: v1 kind: Service metadata: name: test annotations: service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "10" service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "10" spec: ...アプリケーションのGraceful Shutdown
コンテナが安全に終了するためには、それぞれのコンテナがGraceful Shutdownをサポートしている必要がある。
例えば、
Gunicorn
はGraceful Shutdownを対応している。適切にgraceful_timeout
の値を設定すれば問題ない。https://docs.gunicorn.org/en/stable/settings.html
また、アプリケーションコンテナの前に
Nginx
のようなリバースプロキシを立てるのはよくある構成だが、その場合、Nginx
も同様に対応していないと、Nginx
が先に終了し、クライアントに504(Gateway Timeout)
が返ってしまう。
Nginx
自体はGraceful Shutdownに対応しているが、Graceful Shutdownを行うためのシグナルが、SIGTERM
ではなく、SIGQUIT
である。TERM, INT fast shutdown QUIT graceful shutdownhttp://nginx.org/en/docs/control.html
そこで、終了時のシグナルを
SIGTERM
からSIGQUIT
に変更してやる必要がある。DockerfileFROM nginx:<version> ... STOPSIGNAL SIGQUIThttps://github.com/nginxinc/docker-nginx/issues/377
また、タイムアウトは
worker_shutdown_timeout
の値を設定する。http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
コンテナ実行時の複数コマンド実行
SIGTERM
シグナルはコンテナ内のPID 1
のプロセスに送られる。コンテナ起動時に複数コマンドを実行したい場合は、Startup Scriptを使うことはあるが、通常のスクリプトを用いると、そのスクリプトがPID 1
を持つことになり、アプリケーションにシグナルが送られない。
そこで、exec
を用いて、スクリプトのプロセスをアプリケーションのプロセスに変更することで対処できる。Dockerfile... ENTRYPOINT ["./startup.sh"] CMD ["runserver"]startup.sh#!/bin/sh set -e # コマンド exec "$@"PID 1問題
LinuxにおけるPID 1は通常
init
である。init
は全てのプロセスの親であるため、このプロセスが殺されると、システムがダウンしてしまうため、特別扱いされている。具体的には、明示的にハンドラを設定していないシグナルは無視される。NAME kill - send signal to a process NOTES The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.https://man7.org/linux/man-pages/man2/kill.2.html
したがって、アプリケーションサーバが明示的に
SIGTERM
のハンドラを設定していない場合は、プロセスがSIGTERM
を無視してしまい、終了処理が適切に行われない。Node.js
でこれが起きるらしい。この問題の回避方法は「明示的にシグナルをハンドリングする」または、「アプリケーションのプロセスをPID 1以外で立ち上げる」の2つが考えられる。前者はそれぞれで対応すれば良い。前者が難しい場合は、後者を使う必要がある。
Kubernetes 1.17以上の場合は、ShareProcessNamespace を使ってPID 1を回避できる。
manifestapiVersion: v1 kind: Pod metadata: name: test spec: shareProcessNamespace: true ...Kubernetes以外、またはKubernetesのバージョンが低い場合は、 tiniのような軽量initと呼ばれるライブラリを使えば解決できる。
Dockerfile... ENV TINI_VERSION v0.19.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini ENTRYPOINT ["/tini", "--"] CMD ["runserver"]参考
- https://www.amazon.co.jp/dp/4295004804/
- https://text.superbrothers.dev/200328-how-to-avoid-pid-1-problem-in-kubernetes/
- https://ngzm.hateblo.jp/entry/2017/08/22/185224
- https://man7.org/linux/man-pages/man2/kill.2.html
- https://github.com/krallin/tini
- https://docs.gunicorn.org/en/stable/settings.html
- https://stackoverflow.com/questions/58408087/is-there-a-easy-way-to-shut-down-python-grpc-server-gracefully
- https://docs.celeryproject.org/en/stable/userguide/workers.html
- https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/config-conn-drain.html
- https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/
- http://nginx.org/en/docs/control.html
- https://docs.gunicorn.org/en/stable/settings.html
- https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/
- http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
- https://github.com/nginxinc/docker-nginx/issues/377
- 投稿日:2020-07-08T18:30:28+09:00
Kubernetes(Docker)におけるゼロダウンタイムデプロイメント
はじめに
新しいバージョンのアプリケーションをデプロイする時に、アプリケーションをコンテナで運用している場合は、コンテナを作り替える必要がある。デプロイ時に適切な手順を踏まないと、リクエストを正しく捌けずに、クライアントにエラーを返すことになる。これは本番環境で動いているアプリケーションに取ってはクリティカルな問題である。
KubernetesはRollingUpdate
デフォルトで対応しているため、基本的にはKubebernetesに任せておけばうまく行く。しかし、古いPodを停止する時に、正しく設定を行わないと、まだアプリケーションがリクエストを処理中にもかかわらず、Podを停止してしまう。今回はこの問題を解決するために考察したことをまとめた。KubernetesのPodを停止するまでの挙動
Kubernetesの挙動は以下のようになっている。
Kubernetesでは「
preStop
処理 +SIGTERM
処理」と、「ServiceからのPodの除外処理」が非同期で行われる。コンテナはSIGTERM
のシグナルが送られた場合に、適切に処理中のリクエストを捌き切ってから終了するようにする必要がある。そうでなければ、SIGKILL
シグナルがコンテナに送られて強制終了してしまう。したがって、適切なterminationGracePeriodSeconds
を設定する必要がる。
また、Service
は、該当のコンテナに新しいリクエストを送らないように切り離すが、コンテナが処理を行っている途中である場合は、その接続を切断しないようにしなければいけない。Service (LoadBalancer)
LoadBalancerがコンテナに新しいリクエストを送らないようにするとともに、現在行っている処理の接続を切断しないようにするために、
Connection Draining
の設定をする必要がある。例えば、EKSでは、
Connection Draining
の有効化や、タイムアウトの設定を以下のように設定する。manifestapiVersion: v1 kind: Service metadata: name: test annotations: service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "10" service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "10" spec: ...アプリケーションのGraceful Shutdown
コンテナが安全に終了するためには、それぞれのコンテナがGraceful Shutdownをサポートしている必要がある。
例えば、
Gunicorn
はGraceful Shutdownを対応している。適切にgraceful_timeout
の値を設定すれば問題ない。https://docs.gunicorn.org/en/stable/settings.html
また、アプリケーションコンテナの前に
Nginx
のようなリバースプロキシを立てるのはよくある構成だが、その場合、Nginx
も同様に対応していないと、Nginx
が先に終了し、クライアントに504(Gateway Timeout)
が返ってしまう。
Nginx
自体はGraceful Shutdownに対応しているが、Graceful Shutdownを行うためのシグナルが、SIGTERM
ではなく、SIGQUIT
である。TERM, INT fast shutdown QUIT graceful shutdownhttp://nginx.org/en/docs/control.html
そこで、終了時のシグナルを
SIGTERM
からSIGQUIT
に変更してやる必要がある。DockerfileFROM nginx:<version> ... STOPSIGNAL SIGQUIThttps://github.com/nginxinc/docker-nginx/issues/377
また、タイムアウトは
worker_shutdown_timeout
の値を設定する。http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
コンテナ実行時の複数コマンド実行
SIGTERM
シグナルはコンテナ内のPID 1
のプロセスに送られる。コンテナ起動時に複数コマンドを実行したい場合は、Startup Scriptを使うことはあるが、通常のスクリプトを用いると、そのスクリプトがPID 1
を持つことになり、アプリケーションにシグナルが送られない。
そこで、exec
を用いて、スクリプトのプロセスをアプリケーションのプロセスに変更することで対処できる。Dockerfile... ENTRYPOINT ["./startup.sh"] CMD ["runserver"]startup.sh#!/bin/sh set -e # コマンド exec "$@"PID 1問題
LinuxにおけるPID 1は通常
init
である。init
は全てのプロセスの親であるため、このプロセスが殺されると、システムがダウンしてしまうため、特別扱いされている。具体的には、明示的にハンドラを設定していないシグナルは無視される。NAME kill - send signal to a process NOTES The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.https://man7.org/linux/man-pages/man2/kill.2.html
したがって、アプリケーションサーバが明示的に
SIGTERM
のハンドラを設定していない場合は、プロセスがSIGTERM
を無視してしまい、終了処理が適切に行われない。Node.js
でこれが起きるらしい。この問題の回避方法は「明示的にシグナルをハンドリングする」または、「アプリケーションのプロセスをPID 1以外で立ち上げる」の2つが考えられる。前者はそれぞれで対応すれば良い。前者が難しい場合は、後者を使う必要がある。
Kubernetes 1.17以上の場合は、ShareProcessNamespace を使ってPID 1を回避できる。
manifestapiVersion: v1 kind: Pod metadata: name: test spec: shareProcessNamespace: true ...Kubernetes以外、またはKubernetesのバージョンが低い場合は、 tiniのような軽量initと呼ばれるライブラリを使えば解決できる。
Dockerfile... ENTRYPOINT ["/tini", "--"] CMD ["runserver"]参考
- https://www.amazon.co.jp/dp/4295004804/
- https://text.superbrothers.dev/200328-how-to-avoid-pid-1-problem-in-kubernetes/
- https://ngzm.hateblo.jp/entry/2017/08/22/185224
- https://man7.org/linux/man-pages/man2/kill.2.html
- https://github.com/krallin/tini
- https://docs.gunicorn.org/en/stable/settings.html
- https://stackoverflow.com/questions/58408087/is-there-a-easy-way-to-shut-down-python-grpc-server-gracefully
- https://docs.celeryproject.org/en/stable/userguide/workers.html
- https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/config-conn-drain.html
- https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/
- http://nginx.org/en/docs/control.html
- https://docs.gunicorn.org/en/stable/settings.html
- https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/
- http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
- https://github.com/nginxinc/docker-nginx/issues/377
- 投稿日:2020-07-08T14:58:33+09:00
Linuxでいろいろ調査
はじめに
調査の目的はいろいろですが、調査に利用した内容の備忘録です。
コマンドを使ってみる
- top
- vmstat
- ps
- free
- tcpdump
- printenv
- size
- objdump
- readelf
- ldd
- netstat
- uptime
- lsof
- lspci
- uname
- ulimit
- perf
- strace
- 特定システムコールのみトレース
- 特定システムコールはトレースしない
- システムコールの実行時刻、処理時間
- bootchart
- vnstat
- iostat
- sar
- pgrep
- pmap
- debugfs
環境変数を使ってみる
- LD_DEBUG
解析してみる
GNU GLOBAL
タグ作成
gtags -vHTML化
htags -sanFOpenGrok
gcc
- --export-dynamic
- --version-script
- --start-group
- --end-group
- 投稿日:2020-07-08T11:08:43+09:00
コマンド備忘録
Linux
curl
サーバから、もしくはサーバへデータ転送を行うコマンド.
curlを使ってPOSTやDELETEを行ったり、cookieからSessionを読み込むことができる.curl <option> <url>参考
curl コマンド 使い方メモ
curlコマンドでapiを叩くtouch
ファイルの最終更新日を変更するコマンド.
「touch ファイル名」で実行した時間がファイルの最終更新日になる.touch <option> <file>
tree
今いるディレクトリ以下のディレクトリ構造を表示するコマンド
treepwd
今いるディレクトリまでのPathを表示するコマンド
pwd
windows
windowsのコマンド
dir
カレントディレクトリの中身を参照する
dir
call
バッチファイルからバッチファイルを起動するコマンド.
※バッチファイルとは
→バッチ処理を行うファイル(コマンドをまとめて一括処理してくれるファイル).
- 投稿日:2020-07-08T02:35:23+09:00
「WebShellQuickScanner」Linuxサーバの指定フォルダーのPHPファイル中に、WebShellと高リスクファイルを速いて探し出すのクイックチェックツール,そして、検査結果をTelegramにプッシュする。
「WebShellQuickScanner」とは
「WebShellQuickScanner」は、Linuxサーバの指定フォルダーのPHPファイル中に、WebShellと高リスクファイルを速いて探し出すのクイックチェックツール,そして、検査結果をTelegramにプッシュする。
「Telegram」はTelegram Messenger LLPが開発するインスタントメッセージシステムである。詳細はこちら(Telegram - ウィキペディア)をクリックしてください。
この記事は、日本語の使用ドキュメントとして発表されます。
「WebShellQuickScanner」プロジェクトのリポジトリ
Github: DeepSkyFire/WebShellQuickScanner
「WebShellQuickScanner」について
Linuxサーバの指定フォルダーのPHPファイル中に、WebShellと高リスクファイルを速いて探し出すのクイックチェックツール,そして、検査結果をTelegramにプッシュする。
しかし、検出されたファイルは削除されません。だから、これらのファイルをどうするかはあなた自分自身を決断するです。
「WebShellQuickScanner」にクイックスタート
「WebShellQuickScanner」のダウンロード
wget --no-check-certificate https://raw.githubusercontent.com/DeepSkyFire/WebShellQuickScanner/master/src/WebShellScanner.sh && chmod +x WebShellScanner.shクイックチェックをスタート
bash WebShellScanner.sh -p /data/www-data(ターゲットフォルダーを指定する)「WebShellQuickScanner」の使用方法の詳細
- 必要の依存関係
もし、検査結果をTelegramにプッシュしての機能を利用するためには、OSにcURLをインストールするは必要があります。
- 検査結果をTelegramにプッシュする
この機能を利用するためには、まず、Telegramで
@BotFather
に新しいBOTを申し込みします。そして、Telegramで@userinfobot
を使って、自分のアカウントのCHAT_IDを確認してください。注意! 現在、Telegramでは、メッセージに送信できる最大文字数を制限するようになりました。最大文字数は4096文字。もし検査結果の文字数が4096文字を超えると送信失敗となります。その以後、私は新しいプッシュ方法を更新する予定です。*
- ホスト名(Host Name)について
ホスト名を自分で指定することができます。ホスト名を指定しない場合、スクリプトは自動的にOSからデフォルトのホスト名を読み込みます。
- ログファイルの保存について
ログファイルをサーバー中に保存したい場合は、以下の設定のような設定しましょう:
bash WebShellScanner.sh -p /data/www-data -l /home/wwwwlogs注意! ログ保存フォルダーのアドレスの末尾に「/」記号を書かないでください。
- フルデモ
もし、あなたは「/data/www-data」フォルダーを検査し、ログファイルを「/home/wwwlogs」フォルダーに保存し、そして、「MyServer1」のホスト名を指定した、検査結果をTelegramにプッシュするの場合は、以下の設定にような設定しましょう:
bash WebShellScanner.sh -p /data/www-data -t TELEGRAM_BOT_TOKEN -c TELEGRAM_CHAT_ID -n MyServer1 -l /home/wwwwlogs
ヘルプメッセージを表示する
bash WebShellScanner.sh -h定期点検
Linux OSから
crontab -e
を使って、スキャンタスクを設定します。例:
15 4 * * * "/root"/WebShellScanner.sh -p "/data/www-data" -t "TELEGRAM_BOT_TOKEN" -c "TELEGRAM_CHAT_ID" -n "MyServer1" -l "/home/wwwlogs" > /dev/null上記の例では、1日1回、午前4時15分にスキャンタスクが実行される。
パラメータ(変数)の説明
WebShellScanner.sh [-h] [-p <ターゲットフォルダー>] [-t <TELEGRAM BOT TOKEN>] [-c <TELEGRAM CHAT ID>] [-n <ホスト名>] [-l <ログファイルの保存フォルダー>]使用可能なパラメータ:
-h ヘルプメッセージを表示する. オプションパラメータ(変数). -p <ターゲットフォルダー> 検査したいなフォルダー. -t <TELEGRAM BOT TOKEN> Telegram Bot Token. オプションパラメータ(変数). -c <TELEGRAM CHAT ID> Telegram Chat id. オプションパラメータ(変数). -n <HostName> カスタムホスト名. オプションパラメータ(変数). -l <ログファイルの保存フォルダー> ログファイルの保存フォルダー(ログ保存フォルダーのアドレスの末尾に「/」記号を書かないでください). オプションパラメータ(変数).オープンソースライセンス
- 投稿日:2020-07-08T01:56:05+09:00
OVSで実現するERSPANデスティネーションの構築(冗長化もあるよ)/2.6MB GIF動画アリ
概要
本ドキュメントは、公式ドキュメント上の実装例と冗長化のアイデアについて実現性を検証した結果を備忘録的に残したものとなります。
ERSPAN+---------------+ +--------------------+ | ERSPAN SOURCE +--------[L3/IP Network]------->+ ERSPAN DESTINATION | +---------------+ +--------------------+某社のスイッチにてERSPANというパケットミラーリングのプロトコルを使用することとなった。ERPSANではミラーしたパケットをトンネリングプロトコルで包み、ネットワークを超えて転送する。
このときERSPANを終端しキャプチャ装置にパケットを転送する仕組みが何らか必要となる。
パケットキャプチャソリューションの一部や、一部のルータ等においては、ERSPANを終端する機能を有するが、いずれも高価である。
そこでOSS仮想スイッチである、Open vSwitchを用いてERPSANを終端するための実装を検討した。また実装に当たっては商用での稼働も検討し、冗長化についての検討も行った。
数秒単位での冗長化切替を実現できる、Open vSwitchでの実装が可能であることを確認した結果をここに記す。
はじめに
ERSPANとは
ERSPANはスイッチでキャプチャしたパケットをネットワークを超えて転送するためのCisco社が提唱・実装しているプロトコルである(Internet draftにもなっている1)。
ERSPANではスイッチでミラーしたパケット(Ethernetフレーム)をトンネリングプロトコルであるGREを用いてカプセリング化し、トンネルエンドポイントに指定されたリモートのIPアドレスに向けてミラーされたパケット(Ethernetフレーム)を運ぶ。この時、GREヘッダと、ミラーされたErhternetフレームの間にERSPANヘッダを差し込む、結果プロトコルスタックとしては以下のようになる。
+---------------+ | Some IP | | Playload | +---------------+ | IP(Inner) | +---------------+ |Ethernet(Inner)| +---------------+ | ERSPAN | +---------------+ | GRE | +---------------+ | IP(Outer) | +---------------+ |Ethernet(Outer)| +---------------+ | Physical | +---------------+ERSPANにはいくつかバージョンが存在するが、ここではその説明は割愛する。
ERSPANデスティネーションについて
上述の通り、ERSPANにおいてはGREによりパケットを転送する。 ERSPANのパケットはGREヘッダが付けられたIPパケットとして、ただ単純ににFIBテーブルに従い転送し、IPネットワークの中では通常のIPパケットとして処理される。
デスティネーションにおいてはパケットキャプチャ装置等に向けてこのGREおよびERSPANヘッダを取り除いたパケットを転送する。
今回このERSPANデスティネーションをOSSを用いて実装する。
Open vSwitchのERSPAN対応
Open vSwitch(以下OVS)では ver 2.10 以上 かつ Linux kernel 4.18以上で ERPSPAN プロトコルに対応している2。そのため、今回はOVSを用いた実装について検討する。
環境について
実際の設定例に先立ち、検証に使用したハードウェアやソフトウェアの情報と最終的にFixした環境を紹介する。
ハードウェア/VMおよび使用したソフトウェアの情報
OVSを用いる部分については2020年現在、OSのディストリビューションに付属しているOVSが2.13.0と比較的新しいリリースのUbuntu 20.04を用いている。
Hypervisor(以後ホストOVSと呼称)
- CPU: AMD Ryzen 5 3600 (6コア 12スレッド)
- Memory: 16GB
- OS: Ubuntu 20.04 LTS
- Linux kernel 5.4.0
- OVS: 2.13.0 (DPDK datapath)
- 別の検証目的でDPDKのOVSをテストしていた環境のためホストOVSはDPDK版を使用
OVS VM(2 VMs/ 以後ゲストOVSと呼称)
- CPU: 2 Cores
- Memory: 1 GB
- OS: Ubuntu 20.04 LTS
- Linux kernel 5.4.0
- OVS: 2.13.0
- keepalaived: 2.0.19
Traffic VM(2 VMs)
- CPU: 2 Cores
- Memory: 1 GB
VM配置およびそれぞれのVMの役割
少々いびつな構成ではあるが、ハイパーバイザにKVMを用いて構築した仮想マシン上のゲストOVSと物理マシンにインストールされたホストOVSを組み合わせて検証環境を構築した。
ハイパーバイザにインストールされたホストOVSがキャプチャ元スイッチ(ERSPANソース)を疑似し、VM上に構築されたゲストOVSがERSPANデスティネーションを疑似する。
Traffic VMはホストOVSによって接続されている。このTraffic VM間でPingによる通信を発生させ、その通信をホストOVS側の設定においてミラーリングし、ゲストOVSにERSPANを用いて転送する。ゲストOVSではホストOVSから送られてきたERSPANのパケットを解き、ゲストOVS内でパケットを所定のポートへミラーする。
ゲストOVSは冗長構成を検討するために2台用意し、アクティブ・スタンバイ構成でのHA構成を取る。
一つのハイパーバイザ上で構築(Guest OVS) (Guest OVS) +--------------+ +--------------+ |ERSPAN Dest 1 | |ERSPAN Dest 2 | +--------------+ +--------------+ +--------------+ +--------------+ | Open vSwitch | | Open vSwitch | | Traffic VM 1 | | Traffic VM 2 | +--------------+ +--------------+ +--------------+ +--------------+ | Ubuntu 20.04 | | Ubuntu 20.04 | | Linux | | Linux | +--------------+ +--------------+ +--------------+ +--------------+ |Guest Machine | |Guest Machine | |Guest Machine | |Guest Machine | +-------+------+ +-------+------+ +-------+------+ +-------+------+ |(vhost user) |(vhost user) |(vhost user) |(vhost user) +-------+-----------------+-----------------+-----------------+------+ | KVM / Open vSwitch 2.13.0 with DPDK datapath | (Host OVS) +--------------------------------------------------------------------+ | Ubuntu 20.04 LTS / Kernel 5.4.0 | +--------------------------------------------------------------------+ | Host Machine AMD Ryzen 5 3600 / 16GB RAM | +--------------------------------------------------------------------+ホストOVS上のネットワーク構成
ホストOVSとゲストOVSの、それぞれの間はL2で同一セグメントで接続する。
また、Traffic VM間でホストOVSを経由したPingを発生させ、ホストOVSを通過したPingパケットをERSPANでミラーリングし、ゲストOVSに転送する構成で試験を行う。
ERSPANデスティネーションとなるゲストOVSはVLAN 5に所属し、キャプチャ対象となるトラフィックを生成するTraffic VMはVLAN 3に所属する。
ERSPANのトンネルポートの送信元IPアドレスを設定するためにVLAN 5にはInternal Portを生成し、IPアドレスを割り当てる。また、ERSPANのトンネルポート自体はホストOVSのVLAN 10に作成している(理由は後述)。
ERSPANデスティネーションとなるゲストOVS同士はVRRPによってVIPを共有する。
ホストOVSはこのVIPに対してのERSPANソースセッションを作成する。ホストOVS内のブリッジ/VLAN構成について(最終形)VRRP Ping |-----------------| |---------------->| +--------------+ +--------------+ +--------------+ +--------------+ |ERSPAN Dest 1 | |ERSPAN Dest 2 | | Traffic VM 0 | | Traffic VM 1 | +------+-------+ +------+-------+ +------+-------+ +------+-------+ | .2(VIP:.10) | .3(VIP:.10) | | +------+-----------------+--+----+ +----+----+ +------+-----------------+-------+ VLAN 5:192.168.50.0/24 |.1 |VLAN 10 V VLAN 3:192.168.0.0/24 br-int +--------+----+ +----+----+ | br-int |Internal Port| |ERPSAN SP|<------+ +-------------+ +---------+ Mirroring Setting from VLAN 3 to ERSPAN SP [ERSPAN source session from .1 to .10] SP: Source-port DP: Destination-portゲストOVS上のネットワーク構成
ゲストOVS内では1つのブリッジを作成し、vNICが所属するVLAN 4と、ミラーされたパケットを流すためのポートが所属する VLAN 2 、 ERSPANデスティネーションに設定されている VLAN 10の三つを用意した。
このOVSのブリッジに対してERSPANデスティネーションセッションを作成し、ERSPANデスティネーショポートからモニターポート向けへのミラー設定を投入する3。
ERSPANデスティネーションVM内のOVSのブリッジ/VLAN構成について(最終形)Mirroring setting from DP to MP +----------------+ [ERSPAN dest session from .10 to .1] | V +-------------+ +----+----+ +------------+ |Internal Port| |ERSPAN DP| |Monitor Port| +------+------+ +----+----+ +-----+------+ | .2(VIP:.10) | | +--+-------+------+ +----+----+ +-----+------+ | VLAN 4:192.168.50.0/24 VLAN 10 VLAN 2 +--+--+ br0 br0 br0 |vNIC | +-----+ DP: Destination-port MP: Monitor-port設定例の記載にあたって
本ドキュメントはERSPANの設定についてのナレッジを残すことを目的としているため、OVSのインストールやKVMでのVMの作成、OVSとVMの接続などはアウトオブスコープとし、ここではホストOVSのブリッジの作成、ポートの作成、VMの作成、VLANの設定等は終わっている前提で進めます。
必要に応じて、公式ドキュメントや、各種チュートリアル等を参照してください。ゲストOVS/ERSPANデスティネーションの設定
前提条件
ERSPANデスティネーションVM内のOVSのブリッジ/VLAN構成について(初期状態)(Empty)
- OVSのインストールは済んでいる
- ERSPANパケットを受信するVMのvNICは
ens4
としてOSに認識されているens4
とは別にOSにリモートログインでき、かつインターネットアクセスできるvNICが付与されている(この記載例ではens3
がそのvNICとなっており、linux bridgeからDHCPでIPアドレスを振られてます)- 設定についてはほぼ重複するため、二つあるゲストOVSのうち、片側のVMのみ記載しています。適宜読み替えてもう一方のVMにも設定ください。
ブリッジの追加とブリッジへのvNICの追加
# ovs-vsctl add-br br0 #ブリッジに追加 # ovs-vsctl add-port br0 ens4 tag=4 #ブリッジへの受信ポートの追加 # ovs-vsctl set port br0 tag=4 #内部ポートをVLAN 4所属に変更 # ip a add 192.168.50.2/24 dev br0 #VMによりIPアドレスを変更 # ip link set up br0 # ip link set up ens4またbr0へ付与したIPアドレスの永続化と、ens4の有効化のためにnetplanにより設定を永続化する。
/etc/netplan/60-erspan-dest.yamlnetwork: ethernets: ens4: dhcp4: no dhcp6: no br0: dhcp4: no dhcp6: no addresses: - 192.168.50.2/24 #VMによりIPアドレスを変更 version: 2keepalivedによるVRRPの形成
VRRPによる冗長化を組むために
keepalived
をインストールし、設定する。# apt-get install keepalivedホストOVSとL2接続している関係からか、ホストOVS側でのトンネルエンドポイントに対するARPテーブルがGarpで消えない事象が発生したため、vMAC方式を使用している。L3接続の場合は不要だと思いますが、どこかでARPテーブルをほじられるのことを考えるとvMACにしておいたほうが安全かもしれません。
/etc/keepalived/keepalived.confglobal_defs { router_id 192.168.50.2 #VMによりIPアドレスを変更 vrrp_skip_check_adv_addr vrrp_garp_interval 1 vrrp_garp_master_refresh 10 vrrp_gna_interval 10 } vrrp_instance VI_1 { state BACKUP accept interface br0 virtual_router_id 51 use_vmac vrrp51 advert_int 1 priority 100 virtual_ipaddress { 192.168.50.10/24 } }設定を反映。
# systemctl resatrt keepalived2VMとも設定し、うまく行けばVRRPが組めているので確認する。
VRRPでActiveとなているVMでのipコマンドでの確認結果$ ip a show dev vrrp51 12: vrrp51@br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:33 brd ff:ff:ff:ff:ff:ff inet 192.168.50.10/24 scope global vrrp51 valid_lft forever preferred_lft foreverVRRPでStandbyとなているVMでのipコマンドでの確認結果$ ip a show dev vrrp51 12: vrrp51@br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:33 brd ff:ff:ff:ff:ff:ffERSPANデスティネーションの設定
ERSPANのデスティネーションセッションの設定を入れます。
# ovs-vsctl add-port br0 erspan_dp tag=10 -- \ set Interface erspan_dp type=erspan \ options:key=1 options:remote_ip=192.168.50.1 \ options:erspan_ver=2 options:erspan_dir=1 \ options:erspan_hwid=4ここで作成したトンネルポートをVLANタグを4でも2でもなく、10としているのは
erspan_dp
が所属するVLANを隔離するためとなる。
VLANを隔離しない(たとえばVLAN 4を設定した)場合、キャプチャされたパケットがERSPANポートから飛び出し、ens4などを経由して外部に流出してしまう。
さらに、;逆にVLAN 4内で流通するブロードキャストやマルチキャストパケット(たとえば、ARPリクエストやDHCPリクエストや、今回内部で使用しているVRRPのアドバタイズなど)がERSPANポートに流入する。その結果今回のERSPAN送信元である、ホストOVS向けにそれらのパケットが流出してしまう。そのため、ここではVLANを隔離する目的でERSPANポートである
erspan_dp
をそのほかのVLANとは違うVLANに設定している。もし他に良い手があればご教授ください…。
ERSPANセッションのミラールールの設定
ERSPANデスティネーションセッションでカプセル化を解かれたパケットをモニターポートへ吐き出す設定を追加する。
# ovs-vsctl add-port br0 mport tag=2 -- set Interface mport type=internal # モニターポートを追加 # ovs-vsctl --\ --id=@srcp get port erspan_dp --\ --id=@dstp get port mport --\ --id=@m create mirror name=m0 output-port=@dstp select-src-port=@srcp --\ set bridge br0 mirrors=@m #トンネルポートからモニターポートへのミラー設定を追加 # ip link set up mport必要に応じてモニターポートの永続化設定をnetplanに投入しておく。
/etc/netplan/60-erspan-dest.yaml--- a/60-erspan-dest.yaml 2020-07-06 17:03:20.839471511 +0000 +++ b/60-erspan-dest.yaml 2020-07-06 17:02:03.370304770 +0000 @@ -8,5 +8,8 @@ dhcp6: no addresses: - 192.168.50.2/24 + mport: + dhcp4: no + dhcp6: no version: 2以上で、デスティネーション側の設定は終了です。
ホストOVS/ERSPANソースの設定
前提条件
ホストOVS内のブリッジ/VLAN構成について(初期状態)+--------------+ +--------------+ +--------------+ +--------------+ |ERSPAN Dest 1 | |ERSPAN Dest 2 | | Traffic VM 1 | | Traffic VM 2 | +------+-------+ +------+-------+ +------+-------+ +------+-------+ | | | | +------+-----------------+-------+ +------+-----------------+-------+ VLAN 5 VLAN 3 br-int br-int
- ホストOVSはインストール済み
- ゲストVM類はOVSに接続済み
- OVSのブリッジが作成済みでかつ各VM向けポートにはTag VLANの設定が投入済み
この状態からERSPANに必要な設定を投入する。
ゲストOVSとホストOVS間のVLAN 5でのネットワーク導通の確保
まず、VLAN 5のブリッジに対してERSPANのソースIPアドレスとなるためのIPアドレスを付与する。
ソースIPを付与するポートの名前はvlan5
とし、Internal Port
で作成し、IPアドレスの付与、リンクアップを実施する。# ovs-vsctl add-port br-int vlan5 tag=5 -- set Interface vlan5 type=internal # ip a add 192.168.50.1/24 dev vlan5 # ip link set up vlan5この状態で問題なく疎通できていればホスト側からVIPに対してPingが飛ぶはずです。
$ ping 192.168.50.10 -c 3 PING 192.168.50.10 (192.168.50.10) 56(84) バイトのデータ 64 バイト応答 送信元 192.168.50.10: icmp_seq=1 ttl=64 時間=1.55ミリ秒 64 バイト応答 送信元 192.168.50.10: icmp_seq=2 ttl=64 時間=0.196ミリ秒 64 バイト応答 送信元 192.168.50.10: icmp_seq=3 ttl=64 時間=0.215ミリ秒 --- 192.168.50.10 ping 統計 --- 送信パケット数 3, 受信パケット数 3, パケット損失 0%, 時間 2009ミリ秒 rtt 最小/平均/最大/mdev = 0.196/0.654/1.553/0.635ミリ秒 $ ip nei show 192.168.50.10 192.168.50.10 dev vlan5 lladdr 00:00:5e:00:01:33 DELAYnetplanで上記設定したVLAN 5へのIPアドレスを永続化する。
/etc/netplan/60-network-for-ovs.yamnetwork: ethernets: vlan5: dhcp4: no dhcp6: no addresses: - 192.168.50.1/24 version: 2ERSPANソースセッションの作成
次に、ERSPANソースセッションを作成する。
# ovs-vsctl add-port br-int erspan_sp tag=10 -- \ set In-terface erspan_sp type=erspan \ options:key=1 options:remote_ip=192.168.50.10 \ options:erspan_ver=2 options:erspan_dir=1 \ options:erspan_hwid=4ミラリング設定を追加
最後にVLAN 3からerspan_spに向けたキャプチャの設定を追加する4。
ovs-vsctl --\ --id=@p get port erspan_sp --\ --id=@m create mirror name=m0 select-all=true select-vlan=3 output-port=@p --\ set bridge br-int mirrors=@m
これでキャプチャの設定が完了し、VLAN 3上のトラフィックがすべてERSPANを通じてデスティネーションに届けられているはずです。
試験
実際にゲストOVSにて、ホストOVSで流れるパケットがキャプチャできていることおよび、KVMでゲストOVSのVMを強制シャットダウンし、ゲストOVSでキャプチャセッションが切り替わっていることを確認する。
動画
今回無駄にGIF動画で実際にキャプチャができている様子、切り替わる様子をまとめた。
- 1番目と2番目の窓が、ERSPANデスティネーションVM1台目、2台目それぞれのモニターポートでtcpdumpの実行結果
- 3番目の窓ががLAN 3上でPingを打っているVMのpingの実行結果
- 一番下がホストOVSでの各種操作(状態確認、VMの停止等)
初期状態おいては上から2つ目の窓である、ゲストOVS2においてキャプチャされている。
この上阿智でゲストOVS2で障害を擬似的に発生させ、ゲストOVS1にスイッチオーバされることを確認する。MAC学習の確認
ホストOVSでのMAC学習の状況を確認。現在のVIPはポート6の先にいることがわかる。
キャプチャされたパケットの確認
上から3つ目の窓がVLAN 3上でPingを打っているサーバであり、こちらに出ているシーケンス番号と上段2番目の窓のActive系ゲストOVSのERSPANデスティネーションサーバでキャプチャされた結果を比較している。
障害の疑似・デスティネーションサーバの障害
現在Active系であるになっているゲストOVSのVMを
virsh destroy
で殺し、最上段のStandby系ゲストOVSにERSPANのパケットが吸いこまれ、キャプチャを継続できていることが確認できる。パケットドロップはPingのカウントにして4パケット、約4~5秒程度の切り替わり時間となりました
最後にMAC学習の確認
ホストOVSでのMAC学習の状況を確認し、VIPはポート5の先に移動したことがわかる。
まとめ
OVSを用いることでERSPANのデスティネーションセッションを構築でき、パケットキャプチャを実現できることがわかった。また、Keepalivedと組み合わせることで、ERSPANセションを冗長化することも確認できた。
今回の構成においては負荷試験は実施していませんので、どれぐらいのHWスペックでどれぐらいの処理性能を出すことができるかは今後の課題となる。
以上