LinuxのFirewallの設定をやってみた

自宅にあるLinuxFirewallの設定をいじってなかったんでいじくろうかと。

環境

bookstore@bookstoreUbuntu:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

Firewalldのインストール

LinuxではNetfilterなるものがあり、FirewallやRouterの役割を果たしてくれる。Netfilterの設定を変更するには以下のようなツールが存在する。

  • iptables ... 詳細な設定ができる。NetfilterのIPv4の実装がiptablesというのでそれに付随してるデフォルトのツールかと思う。
  • firewalld ... いくつかのテンプレートから設定を行う。高度なことをしない限りこちらを使うのが普通かと。
  • ufw ... iptables のフロントエンドツール

firewalldもufwも内部ではiptablesを使っている。

Wikipedia iptables

今回はfirewalldを使って簡単に設定をしてみよう。

firewalld.org

aptでインストール

bookstore@bookstoreUbuntu:~$ sudo apt install firewalld
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下のパッケージが新たにインストールされます:
  firewalld
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
342 kB のアーカイブを取得する必要があります。
この操作後に追加で 2,362 kB のディスク容量が消費されます。
取得:1 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 firewalld all 0.8.2-1 [342 kB]
342 kB を 1秒 で取得しました (651 kB/s)
以前に未選択のパッケージ firewalld を選択しています。
(データベースを読み込んでいます ... 現在 269818 個のファイルとディレクトリがインストールされています。)
.../firewalld_0.8.2-1_all.deb を展開する準備をしています ...
firewalld (0.8.2-1) を展開しています...
firewalld (0.8.2-1) を設定しています ...
update-alternatives: /usr/share/polkit-1/actions/org.fedoraproject.FirewallD1.policy (org.fedoraproject.FirewallD1.policy) を提供するために自動モードで /usr/share/polkit-1/actions/org.fedoraproject.FirewallD1.server.policy.choice を使います
man-db (2.9.1-1) のトリガを処理しています ...
ureadahead (0.100.0-21) のトリガを処理しています ...
ureadahead will be reprofiled on next reboot
dbus (1.12.16-2ubuntu2.1) のトリガを処理しています ...
systemd (245.4-4ubuntu3.2) のトリガを処理しています ...

インストールが完了したらサービスも起動する。

bookstore@bookstoreUbuntu:~$ systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-09-20 18:09:41 JST; 1min 38s ago
       Docs: man:firewalld(1)
   Main PID: 4110 (firewalld)
      Tasks: 2 (limit: 19011)
     Memory: 24.7M
     CGroup: /system.slice/firewalld.service
             └─4110 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid

 9月 20 18:09:41 bookstoreUbuntu systemd[1]: Starting firewalld - dynamic firewall daemon...
 9月 20 18:09:41 bookstoreUbuntu systemd[1]: Started firewalld - dynamic firewall daemon.

Firewalldを設定

firewalld concepts

firewalldにはfirwalldデーモンと対話するツールが用意されている。上に載せたリンク先のページの上部にあるのそのツール。firewall-cmdを使うとコマンドラインで設定を行うことができる。他にもツールが用意されていらけれどGUI用らしい。

どのコマンドもfirewalldデーモンとD-Busを使ってやりとりする。D-BusAPIリファレンスはここに載ってた。

firewalld dbus

firewall-cmdをつかってzoneを設定していく。zoneというのはその接続に対する信頼レベルでネットワークインターフェースごとに設定できる。詳細はこちら。

firewalld zones

zoneは事前に設定されているものの中から選ぶこともできるし、自分で作ることもできるらしい。事前に設定されているものはこんな感じで表示できる。

root@bookstoreUbuntu:/home/bookstore# firewall-cmd --list-all-zones
block
  target: %%REJECT%%
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:


dmz
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:


drop
  target: DROP
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:


external
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:


home (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp5s0
  sources:
  services: dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

(以下略)

zoneを切り替えてみる。

root@bookstoreUbuntu:/home/bookstore# firewall-cmd --get-active-zones
dmz
  interfaces: enp5s0
root@bookstoreUbuntu:/home/bookstore# firewall-cmd --set-default-zone=home
success
root@bookstoreUbuntu:/home/bookstore# firewall-cmd --get-active-zones
home
  interfaces: enp5s0

enp5s0インターフェースがdmzからhomeに切り替わった。

zoneにはサービスを関連付けることでどういった通信を許可・拒否するかを定義できる。

firewall service

zoneごとに使用できるサービスはこんな感じで確認できる。

root@bookstoreUbuntu:/home/bookstore# firewall-cmd --zone=dmz --list-services
ssh
root@bookstoreUbuntu:/home/bookstore# firewall-cmd --zone=home --list-services
dhcpv6-client mdns samba-client ssh

zoneは自分で定義することもできる。というわけで特定の送信元からはhttpを許可するzoneを作って割り当ててみようと思う。firewall-cmdだけをつかってもできるんだけど、分かりづらい&設定のバックアップがやりづらいのでXMLのファイルを使って設定をしていこう。

firewalldには設定ファイルを置いておく場所が2つある。

  • /etc/firewalld/ ... ユーザが個別に設定したフィルを置いておくディレクト
  • /usr/lib/firewalld/ ... インストール時点での初期設定が置かれているディレクト
root@bookstoreUbuntu:/home/bookstore# ls /etc/firewalld/
firewalld.conf  firewalld.conf.old  helpers  icmptypes  ipsets  lockdown-whitelist.xml  services  zones
root@bookstoreUbuntu:/home/bookstore# ls /usr/lib/firewalld/
helpers  icmptypes  ipsets  services  zones

設定ファイルを1から作るのではなく、既存の設定ファイルをコピーして個別にカスタマイズするといいと思う。というわけで、home.xmlをもとにカスタマイズする。

root@bookstoreUbuntu:/home/bookstore# cp /usr/lib/firewalld/zones/home.xml /etc/firewalld/zones

firewalldは設定ファイル名をzone名として認識するので、既存のhome設定をコンフリクトしないように名前を変えておこう。

root@bookstoreUbuntu:/home/bookstore# mv /etc/firewalld/zones/home.xml /etc/firewalld/zones/home_custom.xml

home_custom.xmlを編集する。ルールを追加して特定のソースアドレスにはhttp通信を許可する。

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Home with http</short>
  <description>custom home zone</description>
  <service name="ssh"/>
  <service name="mdns"/>
  <service name="samba-client"/>
  <service name="dhcpv6-client"/>

  <rule family="ipv4">
    <source address="192.168.50.126"/>
    <service name="http"/>
    <accept/>
  </rule>

</zone>

firewallを一度リロードする。

root@bookstoreUbuntu:/home/bookstore# firewall-cmd --reload
success

ただしくzone設定ができているとzone一覧で表示される。

home_custom
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
    rule family="ipv4" source address="192.168.50.126" service name="http" accept

あとはこれを割り当てるだけ。

root@bookstoreUbuntu:/home/bookstore# firewall-cmd --set-default-zone=home_custom
success

これで設定が有効になった。

試しにnmapを使ってfirewallの設定が正しく反映されているかを確認してみる。

 ~/D/temp  sudo nmap 192.168.50.35
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-21 19:33 JST
Nmap scan report for bookstoreUbuntu (192.168.50.35)
Host is up (0.0022s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: BC:5F:F4:97:FD:29 (ASRock Incorporation)

Nmap done: 1 IP address (1 host up) scanned in 5.85 seconds

Not shown: 998 filtered ports から998のポートが閉じられている(応答なし)のがわかる。sshとhttpのポートは開いている。

Vimのjumpについて調べてみた

vimのhelp読んでてjumpとかあまり使ってないし理解できていないなと。

jumps

jumpのヘルプは :help jump-motions で確認できる。

jumpってそもそもなんなのかと言うとコマンドを使用してカーソルを別の行に移動させることを指すみたい。vimにはいくつもjump motionコマンドが存在しててこれらを完全に使いこなせると移動が楽になりそう。

コマンド 内容
' {a-z}のマークにジャンプする
` {a-z}のマークにジャンプする
G 指定された count 行にジャンプする。デフォルトでは最終行
/ 全文検索を行い一致する箇所にジャンプする
? 後方検索を行い一致する箇所にジャンプする
n 検索で一致した箇所に前方移動する
N 検索で一致した箇所に後方移動する
% カーソル下の文字列に対応する箇所にジャンプする。例えば括弧など
( count センテンス戻る
) count センテンス進む
{ count パラグラフ戻る
} count パラグラフ進む
:s 置換
:tag タグにジャンプ
L 画面内の最終行から count 行目に移動
M 画面内の中央行へ移動
H 画面内の最初の行から count 行目に移動

jump motionコマンドを利用する時、vimは元いた場所を全て記録してくれる。頭いいですね。記録は :ju :jumps コマンドで表示できる。上が一番古く、下が一番新しいジャンプ箇所で、 > で示されている行が今いる場所みたい。この辺りは直感的。

:ju
 jump   行   列 ファイル/テキスト
   3  1027    0 The "file/text" column shows the file name, or the text at th
   2  1040   57 The pointer will be set at the last used jump position.  The
   1  1054    0 The result is that when repeating CTRL-O you will get back to
>  0  1063   27 jump command (e.g., "G").  The jump list would then become:
   1  1072    0 The line numbers will be adjusted for deleted and inserted li
   2  1102   13 remembered.  The number of entries in the change list is fixe

CTRL-I を使うとジャンプ履歴を進み、 CTRL-O を使うとジャンプ履歴を戻る事ができる。jump 列で示されている値は今いる場所から CTRL-I CTRL-O を何回実行すればそこに辿り着けるかを示している。わかりやすい。使ってみた感じだとファイル/テキスト列の表示内容は今いるファイル以外であればファイル名だけが表示される。

change list jumps

change list jumpsはjumpとほとんど同じなんだけれどその履歴が変更箇所のみになったもの。つまり変更行を行ったり来たりできる。これは知らなかったのでとても役に立ちそう。

変更の記録は :changes で表示する事ができた。内容は :jumps と同じ。 g; で変更を遡り、 g, で変更箇所を進める事ができる。

:changes
変更   行    列  テキスト
    9     3    5 # jumps
    8    44   18 # change list jumps
    7     3    6 # jumps
    6    47  231
    5    47    0
    4    46    0 change list jumpsはjumpとほとんど同じなんだけれどそ
    3    47    6
    2    47    0

ジャンプ履歴と変更履歴(ヘルプだとリストって書いてあった)はどちらも100まで履歴を覚えておいてくれる。つまり、 999g, ってやれば最後の変更箇所にジャンプする事ができる。

Lessのmanページを眺めてみた

Lessのmanページを眺めていたら便利な設定を見つけたので気になったもの順で書き出してみた。manページ眺めるのは暇つぶしに最適なだけでなく、結構役に立つ情報を入手できる。こういう文章をきちんと追える人ってすごいなと思います。

--line-numbers で左側に行番号を表示する事ができる。このオプションは大量のファイルを読み込んだ時に処理が遅くなってしまうのを防ぐためにデフォルトではオフになっているんだけど正直ONにしておいて問題ないと思う。

= で全体のなんバイトあたりを見ているかを表示してくれる。

-+ の後にオプションを続けるとそのオプションのデフォルト設定にリセットしてくれる。いろいろいじくり回して戻したい時に便利かも。例えば -+m として使うとプロンプト表示をshortにできる。 -+M も同じ。つまり、プロンプト表示はデフォルトではshortという事だ。

-!-+ と反対の意味で、オプションを有効にしてくれる。

_ を使えばオプションの現在の設定値を表示してくれる。 _m みたいに使う。

プロンプト表示

-m でプロンプトの表示をmediumに変更する事ができる。既にmedium表示になっていたらshort表示に切り替わる。

-M でプロンプトの表示をlongに変更する事ができる。既にlong表示になっていたらshort表示に切り替わる。

プロンプトの表示形式は別で指定する事ができて、デフォルト値だとmedium、shortの表示はそのときの状況によって変わるようになっている見たい。

ちなみに次が自分の環境のデフォルトでのプロンプト設定値だった。結構長い。

?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\: %x.:?pB%pB\%:byte %bB?s/%s...%t

?から始まるものは条件を表していて、%から始まるものは表示する情報を表している。

最初の部分だけ意味を整理してみよう。

?n

これは最初のプロンプト表示なのかを判定している。最初のプロンプト表示であるならば、次の内容を表示する。

?f%f .?m(%T %i of %m) .

ちょっと複雑だけど、これはピリオドが二つとクエッションが二つあるので二つの内容に分解できる。

?f%f .

これはファイル名がわかるなら、ファイル名を表示するという意味。

?m(%T %i of %m) .

これは一つ以上のファイルを開いていた場合、今開いているファイルのインデックスと開いているファイルの総数を表示するという意味。

つまり、プロンプトを最初に表示する時に、ファイル名がわかるならファイル名を、一つ以上のファイルを開いている場合はその情報を表示するという意味になる。ちょっと複雑で最初は慣れないかもだけど、慣れて仕舞えば簡単に理解できそう。そもそもlessで複数ファイル開けたんだ...。

-P でプロンプトの表示内容を変更できるのでちょっとカスタマイズを試してみた。

?ltTopLine %lt. ?lbBottomLine %lb.

これは画面表示上で上下の行数を表示する。 ?lt?lb はちょっと特殊な扱いで、?lX のXに入る文字列で意味が違ってくる。この例で使っているのは tb でそれぞれ画面上の上下の行を表している。

lesskey

lesskeyと呼ばれるファイルでlessのデフォルト動作を変更できるみたい。ただ、手元のMacにはlesskeyコマンドが入っていなくてマニュアルを見る事ができなかった。ので、後でまとめようと思う。

環境変数

lessは環境変数の値で動作を変更する事ができるみたい。manページのENVIRONMENT VARIABLESに詳しく書いてある。

lessで開いている時に v コマンドでファイルをエディタで開く事ができるんだけれど、エディタは EDITOR 環境変数でしていする事ができる。自分の環境だとデフォルトがviだったのでnvimに変更してみた。

LESS 環境変数にオプションを指定しておくとlessのデフォルトの動作を変更できる。自分は -N -M を指定して常に行番号とロングプロンプトを表示するように変更してみた。ただ、デフォルトの動作設定はlesskeyで行う方がいいのかもしれない。lesskeyの方が設定をファイルに書き出せる分メンテナンスがやりやすそう。

Linuxシステム情報を収集&閲覧するsysstatを使ってみる

sysstatを使ってLinuxのシステム情報を収集してみようかと思います。

構成

sysstatをインストールするLinuxの構成です。

bookstore@bookstoreUbuntu:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

インストール

aptで検索してみた結果がこちら。

bookstore@bookstoreUbuntu:~$ sudo apt search sysstat
ソート中... 完了
全文検索... 完了
isag/focal,focal 12.2.0-2 all
  Interactive System Activity Grapher for sysstat

libsysstat-qt5-0/focal 0.4.2-0ubuntu2 amd64
  Qt-based interface to system statistics

libsysstat-qt5-0-dev/focal 0.4.2-0ubuntu2 amd64
  Qt-based interface to system statistics (dev)

pgcluu/focal,focal 3.1-1 all
  PostgreSQL performance monitoring and auditing tool

recap/focal,focal 2.0.2-1 all
  Generates reports of various information about the server

sysstat/focal 12.2.0-2 amd64
  system performance tools for Linux

最後のやつですね。 apt info で見てみたらホームページ等が記載されてます。

bookstore@bookstoreUbuntu:~$ apt info sysstat
Package: sysstat
Version: 12.2.0-2
Priority: optional
Section: admin
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Robert Luberda <robert@debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 1,524 kB
Depends: lsb-base (>= 3.0-6), ucf (>= 2.003), xz-utils, debconf (>= 0.5) | debconf-2.0, libc6 (>= 2.14), libsensors5 (>= 1:3.5.0)
Recommends: cron | cron-daemon
Suggests: isag
Homepage: http://pagesperso-orange.fr/sebastien.godard/
Task: postgresql-server
Download-Size: 453 kB
APT-Sources: http://jp.archive.ubuntu.com/ubuntu focal/main amd64 Packages
Description: system performance tools for Linux
 The sysstat package contains the following system performance tools:
  - sar: collects and reports system activity information;
  - iostat: reports CPU utilization and disk I/O statistics;
  - tapestat: reports statistics for tapes connected to the system;
  - mpstat: reports global and per-processor statistics;
  - pidstat: reports statistics for Linux tasks (processes);
  - sadf: displays data collected by sar in various formats;
  - cifsiostat: reports I/O statistics for CIFS filesystems.
 .
 The statistics reported by sar deal with I/O transfer rates,
 paging activity, process-related activities, interrupts,
 network activity, memory and swap space utilization, CPU
 utilization, kernel activities and TTY statistics, among
 others. Both UP and SMP machines are fully supported.

ソースはGitHubに上がってました。

https://github.com/sysstat/sysstat

とりあえずインストールします。

bookstore@bookstoreUbuntu:~$ sudo apt install sysstat

インストールしたら、cronの設定ファイルが生成されました。

bookstore@bookstoreUbuntu:~$ cat /etc/cron.d/sysstat
# The first element of the path is a directory where the debian-sa1
# script is located
PATH=/usr/lib/sysstat:/usr/sbin:/usr/sbin:/usr/bin:/sbin:/bin

# Activity reports every 10 minutes everyday
5-55/10 * * * * root command -v debian-sa1 > /dev/null && debian-sa1 1 1

# Additional run at 23:59 to rotate the statistics file
59 23 * * * root command -v debian-sa1 > /dev/null && debian-sa1 60 2

初期設定では10分毎に統計情報の収集と、23:59にログファイルのローテーションをしているみたいです。

インストールだけではどうやら有効になっていないようなので下記ファイルを書き換えます。

bookstore@bookstoreUbuntu:~$ sudo vi /etc/default/sysstat

ENABLED を true にします。

# Default settings for /etc/init.d/sysstat, /etc/cron.d/sysstat
# and /etc/cron.daily/sysstat files
#

# Should sadc collect system activity informations? Valid values
# are "true" and "false". Please do not put other values, they
# will be overwritten by debconf!
ENABLED="true"

sysstatサービスをリスタート。

bookstore@bookstoreUbuntu:~$ sudo systemctl restart sysstat
bookstore@bookstoreUbuntu:~$ systemctl status sysstat
● sysstat.service - Resets System Activity Data Collector
     Loaded: loaded (/lib/systemd/system/sysstat.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2020-09-08 21:53:01 JST; 4s ago
       Docs: man:sa1(8)
             man:sadc(8)
             man:sar(1)
    Process: 18910 ExecStart=/usr/lib/sysstat/debian-sa1 --boot (code=exited, status=0/SUCCESS)
   Main PID: 18910 (code=exited, status=0/SUCCESS)

 9月 08 21:53:01 bookstoreUbuntu systemd[1]: Starting Resets System Activity Data Collector...
 9月 08 21:53:01 bookstoreUbuntu systemd[1]: Finished Resets System Activity Data Collector.

システム情報の閲覧

sysstatサービスが起動するとシステム情報が収集され始めるようです。

sarコマンドでシステム情報を閲覧できるようです。何も指定しない場合はCPUの使用状況が出力されました。

bookstore@bookstoreUbuntu:~$ sar
Linux 5.4.0-45-generic (bookstoreUbuntu)    2020年09月08日   _x86_64_    (8 CPU)

21時53分01秒  LINUX RESTART  (8 CPU)

21時55分01秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
22時05分01秒     all      0.02      0.00      0.08      0.00      0.00     99.89
22時15分01秒     all      0.03      0.00      0.07      0.00      0.00     99.89
Average:        all      0.03      0.00      0.08      0.00      0.00     99.89

インターバルと回数を指定すれば指定された間隔で指定された回数情報を出力します。単位は秒のようです。

bookstore@bookstoreUbuntu:~$ sar 5
Linux 5.4.0-45-generic (bookstoreUbuntu)    2020年09月08日   _x86_64_    (8 CPU)

22時24分04秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
22時24分09秒     all      0.00      0.00      0.10      0.00      0.00     99.90
22時24分14秒     all      0.03      0.00      0.03      0.00      0.00     99.95
22時24分19秒     all      0.00      0.00      0.08      0.00      0.00     99.92
^C

Average:        all      0.01      0.00      0.07      0.00      0.00     99.92

-o オプションを使用すれば結果をファイルに書き込めます。ファイルは -f オプションを使えば読み込んで表示できます。

bookstore@bookstoreUbuntu:~$ sar -o sar20200909 1 5
Linux 5.4.0-47-generic (bookstoreUbuntu)    2020年09月09日   _x86_64_    (8 CPU)

15時51分37秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
15時51分38秒     all      0.00      0.00      0.12      0.00      0.00     99.88
15時51分39秒     all      0.00      0.00      0.12      0.00      0.00     99.88
15時51分40秒     all      0.00      0.12      0.25      0.00      0.00     99.63
15時51分41秒     all      0.12      0.00      0.00      0.00      0.00     99.88
15時51分42秒     all      0.00      0.00      0.00      0.00      0.00    100.00
Average:        all      0.03      0.03      0.10      0.00      0.00     99.85
bookstore@bookstoreUbuntu:~$ ls
sar20200909  ダウンロード  テンプレート  デスクトップ  ドキュメント  ビデオ  ピクチャ  ミュージック  公開
bookstore@bookstoreUbuntu:~$ sar -f sar20200909
Linux 5.4.0-47-generic (bookstoreUbuntu)    2020年09月09日   _x86_64_    (8 CPU)

15時51分37秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
15時51分38秒     all      0.00      0.00      0.12      0.00      0.00     99.88
15時51分39秒     all      0.00      0.00      0.12      0.00      0.00     99.88
15時51分40秒     all      0.00      0.12      0.25      0.00      0.00     99.63
15時51分41秒     all      0.12      0.00      0.00      0.00      0.00     99.88
15時51分42秒     all      0.00      0.00      0.00      0.00      0.00    100.00
Average:        all      0.03      0.03      0.10      0.00      0.00     99.85

ファイルはバイナリ形式で保存されるのでsarコマンドからのみ閲覧できるみたいですね。

bookstore@bookstoreUbuntu:~$ file /var/log/sysstat/sa09
/var/log/sysstat/sa09: data

-o にてファイル名を指定しない場合にはデフォルトのファイルに書き込まれるようです。デフォルトのファイルは /var/log/sysstat ディレクトリ内に一日づつファイルが分かれて保存されています。

bookstore@bookstoreUbuntu:~$ ls /var/log/sysstat
sa08  sa09

これら日付別のファイルはcronにより勝手にシステム情報が収集されて増えていくようですね。ただ、saDD の形式なので一ヶ月のサイクルでファイルが上書きされていくようです。

ちなみに -D オプションを同時に使用すれば YYYYMMDD 形式でファイルを保存できます。こうするとファイルのローテーションでシステム情報を永続的に保持できますね。

bookstore@bookstoreUbuntu:~$ sudo sar -o -D 1 3
Linux 5.4.0-47-generic (bookstoreUbuntu)    2020年09月09日   _x86_64_    (8 CPU)

16時01分38秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
16時01分39秒     all      0.00      0.00      0.00      0.00      0.00    100.00
16時01分40秒     all      0.12      0.00      0.00      0.12      0.00     99.75
16時01分41秒     all      0.00      0.00      0.00      0.00      0.00    100.00
Average:        all      0.04      0.00      0.00      0.04      0.00     99.92
bookstore@bookstoreUbuntu:~$ ls /var/log/sysstat
sa08  sa09  sa20200909

CPU以外のシステム情報

オプションを指定すればCPU以外の情報を閲覧できます。

例えば -r オプションでメモリに関する情報を閲覧できます。

bookstore@bookstoreUbuntu:~$ sar -r
Linux 5.4.0-47-generic (bookstoreUbuntu)    2020年09月09日   _x86_64_    (8 CPU)

08時06分30秒  LINUX RESTART  (8 CPU)

08時15分01秒 kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
08時25分01秒  14940260  15373916    464340      2.85    134356    488360   2690344      8.17    609316    358200         0
08時35分01秒  14933872  15373436    463892      2.85    134468    493944   2709056      8.22    613796    359616         0
08時45分01秒  14629268  15402540    431872      2.65    137404    816900   2289792      6.95    873836    396212        24
08時55分01秒  14587532  15363848    460500      2.83    137552    818896   2686372      8.16    902168    396476         8
09時05分01秒  14586692  15363180    460840      2.83    137616    818908   2686372      8.16    902432    396464        40
Average:     14735525  15375384    456289      2.80    136279    687402   2612387      7.93    780310    381394        14

-b オプションではI/Oに関する情報を閲覧できます。

bookstore@bookstoreUbuntu:~$ sar -b
Linux 5.4.0-47-generic (bookstoreUbuntu)    2020年09月09日   _x86_64_    (8 CPU)

08時06分30秒  LINUX RESTART  (8 CPU)

08時15分01秒       tps      rtps      wtps      dtps   bread/s   bwrtn/s   bdscd/s
08時25分01秒      0.22      0.00      0.22      0.00      0.01      3.05      0.00
08時35分01秒      0.32      0.10      0.22      0.00     18.03      3.15      0.00
08時45分01秒     13.63      8.60      5.04      0.00    878.59   1048.86      0.00
08時55分01秒      0.67      0.10      0.56      0.00      6.23      8.31      0.00
09時05分01秒      0.12      0.00      0.12      0.00      0.00      1.80      0.00
Average:         2.99      1.76      1.23      0.00    180.57    213.03      0.00

-n オプションではネットワークに関する情報を閲覧できるのですが、TCPの情報を見ようとしたら見れませんでした。どうやら情報を収集していないので設定が必要な模様。

bookstore@bookstoreUbuntu:/etc/sysstat$ sar -n TCP
Requested activities not available in file /var/log/sysstat/sa09

sarのmanページを確認したらバックグラウンドでシステム情報を収集するsadcにてSNMP情報を収集してないとみれないぞ、と書いてありました。sysstatのmanページを見たら /etc/sysstat/sysstat/ に設定ファイルがあるようなので確認します。

# sysstat configuration file. See sysstat(5) manual page.

# How long to keep log files (in days).
# Used by sa2(8) script
# If value is greater than 28, then use sadc's option -D to prevent older
# data files from being overwritten. See sadc(8) and sysstat(5) manual pages.
HISTORY=7

# Compress (using xz, gzip or bzip2) sa and sar files older than (in days):
COMPRESSAFTER=10

# Parameters for the system activity data collector (see sadc(8) manual page)
# which are used for the generation of log files.
# By default contains the `-S DISK' option responsible for generating disk
# statisitcs. Use `-S XALL' to collect all available statistics.
SADC_OPTIONS="-S DISK"

# Directory where sa and sar files are saved. The directory must exist.
SA_DIR=/var/log/sysstat

# Compression program to use.
ZIP="xz"

# By default sa2 script generates yesterday's summary, since the cron job
# usually runs right after midnight. If you want sa2 to generate the summary
# of the same day (for example when cron job runs at 23:53) set this variable.
#YESTERDAY=no

# By default sa2 script generates reports files (the so called sarDD files).
# Set this variable to false to disable reports generation.
#REPORTS=false

# The sa1 and sa2 scripts generate system activity data and report files in
# the /var/log/sysstat directory. By default the files are created with umask 0022
# and are therefore readable for all users. Change this variable to restrict
# the permissions on the files (e.g. use 0027 to adhere to more strict
# security standards).
UMASK=0022

SMDC_OPTIONSにSNMPを追加しましょう。

SADC_OPTIONS="-S DISK,SNMP"

ファイルを上書きし、sysstatサービスを再起動。

bookstore@bookstoreUbuntu:/etc/sysstat$ systemctl restart sysstat

しかし、もう一度試してみましたが見れませんでした。

bookstore@bookstoreUbuntu:/etc/sysstat$ sar -n TCP
Requested activities not available in file /var/log/sysstat/sa09

sadcのmanページをよく見てみると、オプションを変更したとしても既存の出力ファイルが有る場合にはそちらの設定が優先されるとのこと。というわけで /var/log/sysstat/ のファイルを全部削除し、sysstatサービスがシステム情報を書き出すのを待ってみたらうまく見れました。

bookstore@bookstoreUbuntu:/etc/sysstat$ sar -n TCP
Linux 5.4.0-47-generic (bookstoreUbuntu)    2020年09月09日   _x86_64_    (8 CPU)

18時45分01秒  active/s passive/s    iseg/s    oseg/s
18時55分01秒      0.00      0.00      0.02      0.02
19時05分01秒      0.00      0.00      0.02      0.02
19時15分01秒      0.00      0.00      0.08      0.06
19時25分01秒      0.00      0.00      0.02      0.02
19時35分01秒      0.00      0.00      0.02      0.02
19時45分01秒      0.00      0.00      0.02      0.02
19時55分01秒      0.00      0.00      0.02      0.02
20時05分01秒      0.00      0.00      0.02      0.02
Average:         0.00      0.00      0.03      0.02

他にもいろいろな機能があるので後でまとめる機会があれば書き足そうと思います。

Linuxにsshで接続する

自宅に使っていないPCがあったのでLinuxをインストールし色々と実験(遊び)できるようにしようかと。メインのPCは別のMacとしたいのでまずはSSHで接続できるように設定します。

構成

接続先のLinuxです。

bookstore@bookstoreUbuntu:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

SSHで接続できるようにする

sshで接続するには接続先にsshサーバをインストールし起動させる必要があります。Ubuntuはインストール時点でsshサーバが入っていないのでまずはsshサーバをインストールします。

bookstore@bookstoreUbuntu:~$ sudo apt install openssh-server

インストールするとsshデーモンが起動しssh接続できるようになります。

bookstore@bookstoreUbuntu:~$ systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-09-06 11:20:41 JST; 28min ago
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 876 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 904 (sshd)
      Tasks: 1 (limit: 19011)
     Memory: 5.1M
     CGroup: /system.slice/ssh.service
             └─904 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

 9月 06 11:20:41 bookstoreUbuntu systemd[1]: Starting OpenBSD Secure Shell server...
 9月 06 11:20:41 bookstoreUbuntu sshd[904]: Server listening on 0.0.0.0 port 22.
 9月 06 11:20:41 bookstoreUbuntu sshd[904]: Server listening on :: port 22.
 9月 06 11:20:41 bookstoreUbuntu systemd[1]: Started OpenBSD Secure Shell server.

クライアントPCから接続してみましょう。

$ ssh bookstoreUbuntu
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-45-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be installed immediately.
0 of these updates are security updates.

Last login: Sun Sep  6 11:20:59 2020 from 192.168.50.126

接続できましたね。

公開鍵暗号を使ってSSH接続する

公開鍵暗号を使えばsshで接続する際にパスワードの入力を省くことができます。クライアントで秘密鍵・公開鍵を作成し、接続先に公開鍵を渡します。

鍵の作成と渡し方はこちらを参考にしました。

https://qiita.com/kazokmr/items/754169cfa996b24fcbf5

ここで詳しく書きませんが、基本は下記のコマンドでできます。

// キーペアの作成
$ ssh-keygen -t rsa

// 公開鍵の転送&設定
$ ssh-copy-id <ユーザ名>@<接続先>

SSH接続の詳細設定

実験的な環境であれば上記のステップで十分ですがもう少し細かい設定項目も見ていきます。sshサーバの設定は /etc/ssh/sshd_config で確認、設定を行うことができるようです。各項目についての説明はこちらに記載されているみたいです。

https://man.openbsd.org/sshd_config

デフォルトで設定ファイルが生成されていて、いくつかコメントアウトされているものもあります。コメントアウトされているものはデフォルトの値です。デフォルト値を変更するにはコメントアウトし、値を変更すればよさそうです。

パスワード入力による認証を無効化し、公開暗号を使った認証のみにしたいので以下 PasswordAuthentication をnoに変更します。

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no

sshdを再起動します。

bookstore@bookstoreUbuntu:~$ systemctl restart sshd
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to restart 'ssh.service'.
Authenticating as: bookstore,,, (bookstore)
Password:
==== AUTHENTICATION COMPLETE ===

これでパスワードによるssh接続を無効にすることができました。

SpringBootアプリケーションのDockerイメージを作る!

SpringBootはおしごとで使うのにDockerイメージ作ったことないなと思って、やっておこうかと。

Google先生に聞いたらSpring 公式ブログがDockerイメージの作り方について書いてました。2つほど見つけましたが、下の記事のほうが詳しく書かれています。このあたりを参考にDockerイメージを作ってみます。

最終的に出来上がったものはGitHubに載せました。(Springのサンプルを今後も作ると思うので、Gradleマルチプロジェクト構成にしています。)

プロジェクト構成

プロジェクトの構成は以下です。

.
├── README.md
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
├── simple-spring-boot-docker
│   ├── Dockerfile
│   ├── README.md
│   └── src
│       └── main
│           ├── java
│           │   └── com
│           │       └── example
│           │           └── spring
│           │               └── docker
│           │                   └── Application.java
│           └── resources
└── spring-boot-docker-multi-stage-build
    ├── Dockerfile
    ├── README.md
    └── src
        └── main
            └── java
                └── com
                    └── example
                        └── spring
                            └── docker
                                └── Application.java

simple-spring-boot-docker がビルドしたJarをコピーしてDockerイメージを作る例。spring-boot-docker-multi-stage-build はDockerマルチステージビルドを使って、Jarを作るステップを含んだDockerfileを書いています。

Gradleのマルチプロジェクトの構成をとっているので、ルートプロジェクトの build.gradle.ktsプラグインや依存関係を定義してます。 subproject ブロックを使うことでサブプロジェクトの設定が一箇所で行なえます。プラグインは以下のようにルートプロジェクトで定義したあと、サブプロジェクトごとに apply で適用していく必要があるようです。

spring-examples/build.gradle.kts at master · BooookStore/spring-examples · GitHub

plugins {
    id("org.springframework.boot") version "2.3.1.RELEASE" apply false
    id("io.spring.dependency-management") version "1.0.9.RELEASE" apply false
    id("java")
}

subprojects {
    apply(plugin = "org.springframework.boot")
    apply(plugin = "io.spring.dependency-management")
    apply(plugin = "java")

    java {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        implementation("org.springframework.boot:spring-boot-starter-web")
    }
}

Dockerイメージを作ってみる

ビルドしたJarをコピーしてDockerイメージを作るのは非常にシンプルです。以下がそのDockerfileですが COPY を使ってJarをコピーしたあと、 ENTRYPOINT でアプリケーションを起動するだけです。

spring-examples/Dockerfile at master · BooookStore/spring-examples · GitHub

FROM openjdk:11-jre-slim
WORKDIR /app
COPY ./build/libs/simple-spring-boot-docker.jar .
ENTRYPOINT ["java", "-jar", "simple-spring-boot-docker.jar"]

マルチステージビルドを使う場合はちょっと複雑な印象です。Dockerfileが以下になります。

spring-examples/Dockerfile at master · BooookStore/spring-examples · GitHub

# Build Application
FROM openjdk:11-jdk-slim AS builder
WORKDIR /app
COPY gradlew .
COPY gradle gradle
COPY build.gradle.kts build.gradle.kts
COPY settings.gradle.kts settings.gradle.kts
COPY spring-boot-docker-multi-stage-build spring-boot-docker-multi-stage-build
RUN ["./gradlew", "spring-boot-docker-multi-stage-build:build"]

# Build Docker Image
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/spring-boot-docker-multi-stage-build/build/libs/spring-boot-docker-multi-stage-build.jar .
ENTRYPOINT ["java", "-jar", "spring-boot-docker-multi-stage-build.jar"]

ステップが2つに分かれています。最初にビルドに必要なリソースをコピーしてJarを作ります。次に最終的なイメージを作ります。

マルチステージビルドを利用するメリットとしてはビルドする環境も含めて統一化できる点かなと思います。こっちのPCだと動くという状況をなくすためにはいいと思いますね。(CI環境とかがあるのであればそちらで担保できますけどね)

このDockerfileを実行するときに知ったのですが、Dockerfileが置いてあるディレクトリの外のファイルをコピーすることはできないみたいです。コピーしようとするとこんなエラーが出てしまいます。

COPY failed: Forbidden path outside the build context: ../ ()

このような場合、docker build コマンドを叩くディレクトリをコピーしたいファイルよりも上位のディレクトリにすればOKです。その場合はDockerfileは docker build コマンドを叩くディレクトリからの相対パスを記述する必要があります。また、コマンドの引数にファイルを指定する必要もあります。

Elasticsearch で Custom Analyzer 使ってみる!

Elasticsearch の Analyzer のカスタマイズ方法を調べてみようと思います。

Custom Analyzer を作る

基本はここに書いてありますね。

前回の記事でも載せましたが、Analyzer には3つの要素があり、カスタムで作る場合はそれらの要素を指定することになります。カスタムで作成した Analyzer は _analyze エンドポイントでも使用できますが、実際にはインデックスまたはクエリのときに使用します。

インデックスに Custom Analyzer を適用するにはこうします。

PUT my_index_2
{
  "settings": {
    "analysis": {
      "analyzer": { (1)
        "my_custom_analyzer": {
          "type": "custom", (2)
          "char_filter": [
            "emoticons"
          ],
          "tokenizer": "punctuation",
          "filter": [
           "lowercase",
           "english_stop"
          ]
        }
      },
      "tokenizer": {
        "punctuation": { (3)
          "type": "pattern",
          "pattern": "[ .,!?]"
        }
      },
      "char_filter": {
        "emoticons": { (4)
          "type": "mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": { (5)
        "english_stop": {
          "type": "stop",
          "stopwords": "_english_"
        }
      }
    }
  }
}

(1) analyzer で独自の Analyzer を定義します。名前は my_custom_analyzer に指定しました。 (2) my_custom_analyzer Analyzer のタイプです。 custom または Built-in の Analyzer を指定します。このオブジェクトに使用する Analyzer の3つの要素を指定します。 (3) ~ (5) tokenizer char_filter filter を定義します。

Custom Analyzer の定義の仕方はわかりやすいですね。(3) ~ (5) では Built-in のものをカスタマイズして使っています。 tokenizer も独自のものをインストールすれば使えるのでしょうね。

ドキュメントには日本語の analysis-kuromoji プラグインのインストール方法が書いてありますね。

上で定義したインデックスの Analyzer を使うにはこう。

POST my_index_2/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "I'm a :) person, and you?"
}
{
  "tokens" : [
    {
      "token" : "i'm",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "_happy_",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "person",
      "start_offset" : 9,
      "end_offset" : 15,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "you",
      "start_offset" : 21,
      "end_offset" : 24,
      "type" : "word",
      "position" : 5
    }
  ]
}

:)_happy_ に変換されました。

Custom でも、Built-int でも、インデックスのフィールドに Analyzer を指定するにはこうします。

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_english": {
          "type": "standard",
          "stopwords": "_english_"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type": "text",
        "analyzer": "standard", (1)
        "fields": {
          "english": {
            "type": "text",
            "analyzer": "std_english" (2)
          }
        }
      }
    }
  }
}

(1) Built-in の Analyzer を指定しました。 (2) Custom Analyzer を指定しました。

このようにすればドキュメントを保存するときに対象のフィールドがそれぞれテキスト解析されます。保存されるのはあくまでもドキュメント本体であり、解析されたテキストで置き換わるわけではないので注意です。

Analyzer を指定できる場所

以下のドキュメントに Analyzer を指定できる場所が書いてあります。

場所は以下の3つですね。

  • Index
  • text field
  • Query

text field への指定は既に載せた例の2つ目と同じです。

Index への指定は例の1つ目とほとんど同じです。違うのは Analyzer の名前を my_custom_analyzer から default に変更する点だけです。

Elasticsearch はドキュメントを保存するときに、テキストをどの Analyzer で解析するのかを、以下の順序で判断します。

  1. field に指定されている Analyzer
  2. analysis.analyzer.default に指定されている Analyzer
  3. standard analyzer

field と analysis.analyzer.default の両方に指定がある場合は field の Analyzer が優先されるわけですね。さらに、特に指定していなければ standard analyzer が使われます。

Query にも Analyzer を指定できるのですが、公式ドキュメン度でも謳っているように、基本は Index または field に指定されているものと同じ Analyzer を使うことをオススメしています。Query は field に Analyzer が設定されている場合はそれを使うのですが、 field の Analyzer がなく Index のみに Analyzer が指定されているだけの場合はその Analyzer を使ってくれないようです。この動きを見る限り、standard analyzer 以外を使うのであれば field ごとに Analyzer を明示指定したほうが良さそうですね。

公式ドキュメントには各 field に明示的に Analyzer を指定するシンプルな方法を取るべきだとも書いてあります。