tanke25616429のアウトプット

IT技術の基本を勉強したことをアウトプットします。Linux、Kubernetes、クラウド中心です。百番煎じくらいだけど誰かの役に立てばそれはそれでうれしい。

コンテナのライフサイクル(入門編)

この記事の目的

コンテナの入門時に割とよく使う概念と操作の意味をまとめる。

なお、対象はLinuxコンテナであり、コンテナを管理するツールとしてはpodman*1を使う。

用語の整理

レジストリ

コンテナイメージを格納する場所のこと。コンテナイメージのバージョン管理や配布を行うことができる。

Docker HubQuayなどの公開されているパブリックレジストリもあれば、自分でOSS等(Docker Registry等)を使って構築するプライベートレジストリもある。パブリックレジストリでは有名なOSS製品の公式イメージが公開されており、コンテナを使うときにそれらを活用できる。

リポジトリ、タグ

リポジトリは関連するコンテナイメージを集めたもののこと。通常、同じ製品で異なるバージョンの集合体である。

例えば、Docker Hubというレジストリnginxという製品のリポジトリnodeという製品のリポジトリがあるという関係性である。レジストリ内に製品ごとのフォルダが切られていて、同じ製品の異なるバージョンのコンテナイメージが各製品のフォルダ内に配置されているというイメージと考えればよい。

バージョンはタグと呼ばれるラベルで識別される。

pull / push

pullはコンテナイメージをレジストリからコンテナを実行するクライアントにダウンロードすること*2。pushはローカルのコンテナイメージをレジストリにアップロードすることである。

ライフサイクル

パブリックレジストリ上のコンテナをローカルのLinuxマシンにダウンロードして実行するシナリオでのライフサイクルを示す。

コンテナイメージのpull

クライアント上でpodman imagesコマンドでダウンロード済みのコンテナイメージを確認する。podman pull nginxコマンドでnginxのイメージをpullする。pull時にタグを指定していないが、この場合はデフォルトでlatestというタグを指定したことになる*3

[root@nuc-centos8 ~]# podman images
REPOSITORY                  TAG      IMAGE ID       CREATED       SIZE
[root@nuc-centos8 ~]# podman pull nginx
Trying to pull docker.io/library/nginx...
Getting image source signatures
Copying blob 6f28985ad184 skipped: already exists
Copying blob 879a7c160ac6 done
Copying blob be704f37b5f4 done
Copying blob 29f7ebf60efd done
Copying blob de58cd48a671 done
Copying blob 158aac73782c done
Copying config 6084105296 done
Writing manifest to image destination
Storing signatures
6084105296a952523c36eea261af38885f41e9d1d0001b4916fa426e45377ffe
[root@nuc-centos8 ~]# podman images
REPOSITORY                  TAG      IMAGE ID       CREATED       SIZE
docker.io/library/nginx     latest   6084105296a9   6 days ago    137 MB

コンテナイメージの実行

podman runコマンドでイメージ(例ではnginx)とコンテナ内で実行するコマンド(例では/bin/bash)を指定しコンテナを実行できる。-itは対話的にシェルで操作する場合を指定するオプションである。

[root@nuc-centos8 ~]# podman ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES
[root@nuc-centos8 ~]# podman run  -it docker.io/library/nginx /bin/bash
root@5fc8e66ca233:/# uname -r
4.18.0-193.el8.x86_64
root@5fc8e66ca233:/# exit
exit

ターミナルをもう一つ立ち上げて確認するとコンテナが存在している。名前を指定していないので自動で名前が付与される(inspiring_albattaniがそれ)。-itを指定した場合、コンテナからexitするとコンテナ自体も停止する。停止後のコンテナを確認する場合はpodman images -aとする。

(exit前)
[root@nuc-centos8 ~]# podman ps
CONTAINER ID  IMAGE                           COMMAND    CREATED         STATUS             PORTS  NAMES
5fc8e66ca233  docker.io/library/nginx:latest  /bin/bash  39 seconds ago  Up 38 seconds ago         inspiring_albattani
(exit後)
[root@nuc-centos8 ~]# podman ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES
[root@nuc-centos8 ~]# podman ps -a
CONTAINER ID  IMAGE                            COMMAND           CREATED        STATUS                      PORTS                 NAMES
5fc8e66ca233  docker.io/library/nginx:latest   /bin/bash         9 minutes ago  Exited (127) 7 minutes ago                        inspiring_albattani

対話が必要なく、デーモンとしてバックグラウンドで立ち上がっていればいいケースでは-dをつけて実行する。以下はhttpdコンテナを実行する例である。ホストの8000番ポートがコンテナの80番ポートに転送されるオプションを-pとして付与している。これでコンテナを実行後、localhostの8000番ポートにhttpアクセスをすると結果が返ってきていることがわかる。なお、見づらいので以降の例ではpodman ps -aしたときに話題の対象としているhttpd以外のコンテナについては記載を省略する(ひとつ前に試したnginxのコンテナが存在するため)。

[root@nuc-centos8 ~]# podman run -d -p 8000:80 docker.io/library/httpd
f5580c4f209e1df4648f2fe93009b9d5896b02b4f6bea527bffef7be29310774
[root@nuc-centos8 ~]# podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
f5580c4f209e  docker.io/library/httpd:latest  httpd-foreground  30 seconds ago  Up 28 seconds ago  0.0.0.0:8000->80/tcp  pedantic_chaum
[root@nuc-centos8 ~]# curl http://localhost:8000
<html><body><h1>It works!</h1></body></html>

このhttpdの例ではコンテナイメージをpullする部分あらかじめ実行してあり、記載は省略している。なお、明示的にコンテナイメージをpullせずにrunした場合でも、podman run実行時に自動でpullしてくれる。

コンテナのstopとstart

前節で実行したhttpdのコンテナをpodman stopコマンドで停止してみる。停止する対象のコンテナはコンテナ名で指定する。

[root@nuc-centos8 ~]# podman stop pedantic_chaum
f5580c4f209e1df4648f2fe93009b9d5896b02b4f6bea527bffef7be29310774
[root@nuc-centos8 ~]# podman ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES

停止後は当然http接続してもつながらない。

[root@nuc-centos8 ~]# curl http://localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused

一度停止したコンテナを再度実行してみる。このときはrunではなくstartを使う。

[root@nuc-centos8 ~]# podman ps -a
CONTAINER ID  IMAGE                            COMMAND           CREATED         STATUS                       PORTS                 NAMES
f5580c4f209e  docker.io/library/httpd:latest   httpd-foreground  9 minutes ago   Exited (0) 5 minutes ago     0.0.0.0:8000->80/tcp  pedantic_chaum
(対象のコンテナ以外は略)
[root@nuc-centos8 ~]# podman start pedantic_chaum
pedantic_chaum
[root@nuc-centos8 ~]# podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
f5580c4f209e  docker.io/library/httpd:latest  httpd-foreground  10 minutes ago  Up 14 seconds ago  0.0.0.0:8000->80/tcp  pedantic_chaum
[root@nuc-centos8 ~]# curl http://localhost:8000
<html><body><h1>It works!</h1></body></html>

コンテナとコンテナイメージの削除

コンテナを停止ではなく削除する。削除するとstartで再実行できなくなる。コンテナを停止してから、podman rmコマンドで削除する*4

[root@nuc-centos8 ~]# podman stop pedantic_chaum
f5580c4f209e1df4648f2fe93009b9d5896b02b4f6bea527bffef7be29310774
[root@nuc-centos8 ~]# podman rm pedantic_chaum
f5580c4f209e1df4648f2fe93009b9d5896b02b4f6bea527bffef7be29310774
[root@nuc-centos8 ~]# podman ps -a
CONTAINER ID  IMAGE                            COMMAND           CREATED         STATUS                       PORTS                 NAMES
(対象のコンテナ以外は略)

この段階では、pullしてあるイメージは削除されていない。

[root@nuc-centos8 ~]# podman images
REPOSITORY                  TAG      IMAGE ID       CREATED       SIZE
docker.io/library/nginx     latest   6084105296a9   6 days ago    137 MB
docker.io/library/httpd     latest   ae15ff2bdcb4   6 days ago    142 MB

イメージの削除にはpodman rmiコマンドを利用する。

[root@nuc-centos8 ~]# podman rmi httpd
Untagged: docker.io/library/httpd:latest
Deleted: ae15ff2bdcb44d66199dc364b273ab5b108fb120bb95f022cedabbfab3253701
[root@nuc-centos8 ~]# podman images
REPOSITORY                  TAG      IMAGE ID       CREATED       SIZE
docker.io/library/nginx     latest   6084105296a9   6 days ago    137 MB

参考にしたもの

用語

https://docs.docker.jp/engine/reference/glossary.html#repository

docs.microsoft.com

www.creationline.com

wiki.aquasec.com

searchitoperations.techtarget.com

www.rworks.jp

podman

access.redhat.com

コンテナライフサイクル

access.redhat.com

www.slideshare.net

その他

codezine.jp

*1:Dockerとほぼ互換のコンテナランタイムツール

*2:ダウンロードした際にクライアント上でコンテナイメージが配置される場所のこともレジストリと呼んでもよさそうだが、あまりそういう用例は見かけなかった。ローカルレジストリとでも呼べば区別できそうだが、調べる限りそれはプライベートレジストリと同じ意味で使われていた。コンテナの置き場所となるだけではなく配布する、という機能を担わない限りはレジストリとは呼ばないのかもしれない。

*3:つまり最新版がダウンロードされる

*4:実行中のコンテナを強制的に削除することもできる。

シェルにおけるリダイレクト等を用いたテキストの処理

本記事

簡単にテキストファイルを作る方法として、エディタでテキストの編集したりechoを何回も実行しない方法があるので、それについて記載する。

catによるテキストファイルの作成

catとだけ打鍵すると、そのあと標準入力に記入した文字列が改行コードで区切られてそのまま標準出力に表示される。表示の上では入力した文字列と出力された文字列が混ざって見える。

# cat
1 ← 入力した文字列
1 ← そのまま出力
2
2
3
3

これを利用して、標準出力だけテキストファイルにリダイレクトすればよい。

# cat > test.txt
1 ← 標準入力だけが見えている
2
3 ← Ctrl+Dを押す
# cat test.txt
1
2
3

または<<EOFを使うこともできる(ヒアドキュメント)。これだとCtrl+Dでシグナルを送らなくてよい。

# cat <<EOF > test.txt
> a
> b
> c
> EOF
# cat test.txt
a
b
c

別に区切り文字はEOFでなくてもよいようである。

# cat <<SHELLCHOTTODEKIRU > test.txt
> x
> y
> SHELLCHOTTODEKIRU
# cat test.txt
x
y

変数展開したくない場合は区切り文字をクオーテーションで囲むとよい。

# cat <<EOF > test.txt
> $LANG
> EOF
# cat test.txt
en_US.UTF-8
# cat <<'EOF' > test.txt
> $LANG
> EOF
# cat test.txt
$LANG

teeと組合せる方法

teeコマンドで標準出力とファイルの両方に出力できる。

# date > test.txt
# cat test.txt
Sat Feb 27 13:28:26 JST 2021
# date | tee test.txt
Sat Feb 27 13:28:35 JST 2021
# cat test.txt
Sat Feb 27 13:28:35 JST 2021

なので、catとteeを組み合わせると記入終わったところ(EOFを入れたところ)でこれまで書いた内容が表示されるから一発で確認できる。

# cat <<EOF | tee test.txt
> a
> b
> EOF
a
b

cat以外の例

上で<<EOFの使い方を紹介したがもちろんcatの専売特許ではないので、別のコマンドでも利用できる。以下は文字列置換の例である。

# tr a A <<EOF
> abc
> EOF
Abc

なお、一行しかないなら<<<で文字列を指定することも可能(ヒアストリング)。

# tr a-e A-E <<<abcdefghij
ABCDEfghij

以下は入力した文字列の中から検索したい文字列にマッチする行だけを標準出力とファイルの両方に出力する例*1

# grep ABC <<EOF | tee test.txt
> ABC
> DEF
> GHI
> ABC
> EOF
ABC
ABC
# cat test.txt
ABC
ABC

Ctrl+DとCtrl+Cの違い

Ctrl+Cは処理を途中で終わらせるもの。Ctrl+DはEOFに対応し入力の終了を指示できるものである。 catでテキストを処理する場合、どちらでも大きな違いはない。catでは都度テキストファイルに書き込んでいくため、中断させても、正常に終了させても同じだからである。

# cat > test.txt
1 ← この後Ctrl+Cを押す
^C
# cat test.txt
1
# cat > test.txt
2 ← この後Ctrl+Dを押す
# cat test.txt
2

最後まで処理が正常に完了していないと正しい結果が得られないものでは動作が変わる。例えば行数をカウントするコマンドwcで試してみる。

# wc
1
2
3 ← この後Ctrl+Dを押す
      3       3       6 ← 結果が出力
# wc
1
2
3 ← この後Ctrl+Cを押す
^C ← 結果が出力されない
#

参考にしたもの

5 入力の終わりとコマンドの強制終了

qiita.com

*1:実際にはこんなことをしたいシーンは思い浮かばないので、あくまでこんなこともできるという例である

SELinuxの基本

SELinuxとは

Linuxのセキュリティ機構。通常のLinuxパーミッションの仕組みより細かい権限管理を集中管理でできるようにしている。

権限管理は、何(権限管理対象)に対して、誰(識別方法)が、どのようなことができる(操作)かを規定する。この観点で、パーミッションSELinuxの比較は以下。

  • パーミッション
    • 権限管理の対象 : ファイルとプロセス等
    • 識別方法 : uid, gid
    • 操作 : r (read), w (write), x(execute)
  • SELinux
    • 権限管理の対象 : オブジェクトクラス(ファイル、プロセス、ソケット、 TCP/UDP ポート、共有メモリ、パイプ等のOS が提供するリソースやSELinux 対応アプリケーションが管理するdbus, systemd のサービス等のリソース)
    • 識別方法 : タイプ(ファイル、ディレクトリ、デバイスといったシステムリソースに付与されるラベル)*1
    • 操作:オブジェクトクラスごとに定義された細かい操作

セキュリティコンテキスト

セキュリティコンテキストとはファイル、プロセス、ユーザといったリソースに付与されるラベルのこと。ユーザ識別子:ロール識別子:タイプ(ドメイン)識別子:レベルというフォーマットで示される。lsidps等のコマンドに-Zを付与することで確認できる。

[root@kvm-centos8 ~]# ls -lZ /etc/bashrc
-rw-r--r--. 1 root root system_u:object_r:etc_t:s0 3019 May 15  2020 /etc/bashrc

動作モード

SELinuxには3つの動作モード、Enforcing, Permissive, Disabledがある。

  • Enforcing SELinuxが有効であり、アクセス制御に違反する操作は拒否されるモード。監査ログにも記録される。

  • Permissive SELinuxが有効であるが、アクセス制御に違反する操作は監査ログに記録されるのみで拒否されない。

  • Disabled SELinuxが無効の状態である。

現在のモードはgetenforceコマンドで確認できる。一時的にモードを変更する場合(例えばSELinuxトラブルシューティングのためEnforcing→Permissiveと変更する等)は、setenforceコマンドを使う。

[root@kvm-centos8 ~]# getenforce
Enforcing
[root@kvm-centos8 ~]# setenforce
usage:  setenforce [ Enforcing | Permissive | 1 | 0 ]
[root@kvm-centos8 ~]# setenforce 0
[root@kvm-centos8 ~]# getenforce
Permissive

再起動後も永続的にモードを変更したい場合は、/etc/selinux/configSELINUX=の行を書き換える。反映にはシステム再起動が必要。

[root@kvm-centos8 ~]# vi /etc/selinux/config
[root@kvm-centos8 ~]# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
#SELINUX=permissive
# SELINUXTYPE= can take one of these three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

論理パラメータ

ある目的に必要なルールを 1 つにまとめた2値のパラメータで*2、これを変更することでポリシーが適用できる範囲を調整できる。例えば、Webサーバにおいてユーザのホームディレクトリを公開する際のケースを考える。その場合、Apache HTTP Serverのプロセスがユーザーのホームディレクトリにアクセスしてよいかどうか、というポリシー(httpd_enable_homedirs)がありこれが論理パラメータの1つの例である。 SELinuxのルールでこれが禁止されている場合は、たとえパーミッションで許可されていてもアクセスは許可されない。

以下に操作例を示す。SELinuxにおいて、Apache HTTP Serverがホームディレクトリにアクセスすることが許可されていれば特定のファイル(/home/testuser/www/index.html)が表示され、アクセスが許可されていなければデフォルトのファイルが表示されるというシナリオを考える。

準備

ホームディレクトリの配下に以下のファイルを用意する。

[root@nuc-centos8 ~]# vi /home/testuser/www/index.html
[root@nuc-centos8 ~]# cat /home/testuser/www/index.html
Httpd process can access homedir!

Apache HTTP Serverの設定を書き換える。

[root@nuc-centos8 ~]# cat /etc/httpd/conf/httpd.conf
(省略)
#DocumentRoot "/var/www/html"
DocumentRoot "/home/testuser/www"

#
# Relax access to content within /var/www.
#
#<Directory "/var/www">
<Directory "/home/testuser/www"> # 書き換え
    AllowOverride None
    # Allow open access:
    Require all granted
</Directory>

#<Directory "/var/www/html">
<Directory "/home/testuser/www"> # 書き換え
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.4/mod/core.html#options
    # for more information.
    #
    Options Indexes FollowSymLinks

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    AllowOverride None

    #
    # Controls who can get stuff from this server.
    #
    Require all granted
</Directory>
(省略)

書き換え後にhttpdをリスタートして設定ファイルを反映しておく。

[root@nuc-centos8 ~]# systemctl restart httpd

また、この時点でのSELinuxがEnforcingになっていることを確認する。

[root@nuc-centos8 ~]# getenforce
Enforcing

動作確認

論理パラメータhttpd_enable_homedirsの値を確認する。

[root@nuc-centos8 ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off

offになっているため、ホームディレクトリへのApache HTTP Serverのアクセスはできない。curlで確認する。文字化けしているが、デフォルトのファイルが表示されていることがわかる。

[root@nuc-centos8 ~]# curl http://localhost
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE HTML>
<html lang="en">
  <head>
    <title>CentOS 提供的 Apache HTTP 服?器???</title>
    <meta charset="utf-8"/>
(省略)

論理パラメータhttpd_enable_homedirsの値を変更する。

[root@nuc-centos8 ~]# setsebool httpd_enable_homedirs on
[root@nuc-centos8 ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on

on に変更したためホームディレクトリに配置したファイルにアクセスできていることがわかる。

[root@nuc-centos8 ~]# curl http://localhost
Httpd process can access homedir!

もう一度、論理パラメータをoffに戻し、今度はSELinuxをPermissiveに変更する。

[root@nuc-centos8 ~]# setsebool httpd_enable_homedirs off
[root@nuc-centos8 ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
[root@nuc-centos8 ~]# setenforce
usage:  setenforce [ Enforcing | Permissive | 1 | 0 ]
[root@nuc-centos8 ~]# setenforce 0
[root@nuc-centos8 ~]# getenforce
Permissive

SELinuxがPermissiveなので、ルール違反の処理(Apache HTTP Serverのホームディレクトリへのアクセス)があっても拒否はされない。

[root@nuc-centos8 ~]# curl http://localhost
Httpd process can access homedir!

監査ログにはこのアクセスは記録されていることがわかる。

[root@nuc-centos8 ~]# tail -f /var/log/audit/audit.log
(省略)
type=AVC msg=audit(1613982582.096:66562): avc:  denied  { getattr } for  pid=170913 comm="httpd" path="/home/testuser/www/index.html" dev="dm-5" ino=139 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1613982582.096:66563): avc:  denied  { read } for  pid=170913 comm="httpd" name="index.html" dev="dm-5" ino=139 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file permissive=1
(省略)

ポリシータイプ

タイプ(ドメイン)がシステムリソースをどのように利用できるかを定義したアクセス制御のセットをポリシーと呼ぶ。ポリシーには複数の種類がある。以下は例である。

  • targeted ポリシー
  • minimumポリシー
  • mlsポリシー

CentOSではtargetedポリシーがデフォルトで採用されている。それ以外のポリシーを利用する場合は別途インストールするか、自作のポリシーを用意する必要がある。

以下はminimumポリシーを導入する実行例である。 最初の時点ではtargetedポリシーしか存在しない。

[root@virtualbox-centos7 ~]# ls /etc/selinux/
config  final  semanage.conf  targeted  tmp
[root@virtualbox-centos7 ~]# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

後で突き合わせるため、論理パラメータの一覧をテキストに保存しておく。

[root@virtualbox-centos7 ~]# getsebool -a > targeted.txt

minimumモードをインストールし、設定ファイルを書き換え、システムを再起動する。

[root@virtualbox-centos7 ~]# yum install -y selinux-policy-minimum
(省略)
依存性を更新しました:
  selinux-policy.noarch 0:3.13.1-268.el7_9.2
  selinux-policy-targeted.noarch 0:3.13.1-268.el7_9.2

完了しました!
[root@virtualbox-centos7 ~]# vi /etc/selinux/config
[root@virtualbox-centos7 ~]# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
#SELINUXTYPE=targeted
SELINUXTYPE=minimum #書き換え
[root@virtualbox-centos7 ~]# reboot

再起動後、sestatusコマンドでモードを確認する*3

[root@virtualbox-centos7 ~]# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             minimum
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      31

minimumモードとtargetedモードで論理パラメータの違いを比較する。on/offの違いのある個所もあるが(httpd_dbus_avahi等)、そもそも論理パラメータの数がtargetedモードのほうが多いことがわかる(+のついている行)。

[root@virtualbox-centos7 ~]# getsebool -a > minimum.txt
[root@virtualbox-centos7 ~]# diff -u minimum.txt targeted.txt
--- minimum.txt 2021-02-22 08:21:28.417891542 +0000
+++ targeted.txt        2021-02-21 21:22:37.463692100 +0000
@@ -1,20 +1,85 @@
+abrt_anon_write --> off
+abrt_handle_event --> off
+abrt_upload_watch_anon_write --> on
+antivirus_can_scan_system --> off
+antivirus_use_jit --> off
 auditadm_exec_content --> on
 authlogin_nsswitch_use_ldap --> off
 authlogin_radius --> off
 authlogin_yubikey --> off
+awstats_purge_apache_log_files --> off
+boinc_execmem --> on
+cdrecord_read_content --> off
+cluster_can_network_connect --> off
+cluster_manage_all_files --> off
+cluster_use_execmem --> off
+cobbler_anon_write --> off
+cobbler_can_network_connect --> off
+cobbler_use_cifs --> off
+cobbler_use_nfs --> off
+collectd_tcp_network_connect --> off
+condor_tcp_network_connect --> off
+conman_can_network --> off
+conman_use_nfs --> off
+container_connect_any --> off
+cron_can_relabel --> off
+cron_system_cronjob_use_shares --> off
+cron_userdomain_transition --> on
+cups_execmem --> off
+cvs_read_shadow --> off
 daemons_dump_core --> off
 daemons_enable_cluster_mode --> off
 daemons_use_tcp_wrapper --> off
 daemons_use_tty --> off
+dbadm_exec_content --> on
+dbadm_manage_user_files --> off
+dbadm_read_user_files --> off
 deny_execmem --> off
 deny_ptrace --> off
 dhcpc_exec_iptables --> off
+dhcpd_use_ldap --> off
 domain_can_mmap_files --> on
 domain_can_write_kmsg --> off
 domain_fd_use --> on
 domain_kernel_load_modules --> off
+entropyd_use_audio --> on
+exim_can_connect_db --> off
+exim_manage_user_files --> off
+exim_read_user_files --> off
+fcron_crond --> off
+fenced_can_network_connect --> off
+fenced_can_ssh --> off
 fips_mode --> on
+ftpd_anon_write --> off
+ftpd_connect_all_unreserved --> off
+ftpd_connect_db --> off
+ftpd_full_access --> off
+ftpd_use_cifs --> off
+ftpd_use_fusefs --> off
+ftpd_use_nfs --> off
+ftpd_use_passive_mode --> off
+ganesha_use_fusefs --> off
+git_cgi_enable_homedirs --> off
+git_cgi_use_cifs --> off
+git_cgi_use_nfs --> off
+git_session_bind_all_unreserved_ports --> off
+git_session_users --> off
+git_system_enable_homedirs --> off
+git_system_use_cifs --> off
+git_system_use_nfs --> off
+gitosis_can_sendmail --> off
+glance_api_can_network --> off
+glance_use_execmem --> off
+glance_use_fusefs --> off
 global_ssp --> off
+gluster_anon_write --> off
+gluster_export_all_ro --> off
+gluster_export_all_rw --> on
+gluster_use_execmem --> off
+gpg_web_anon_write --> off
+gssd_read_tmp --> on
+guest_exec_content --> on
+haproxy_connect_any --> off
 httpd_anon_write --> off
 httpd_builtin_scripting --> on
 httpd_can_check_spam --> off
@@ -28,14 +93,14 @@
 httpd_can_network_memcache --> off
 httpd_can_network_relay --> off
 httpd_can_sendmail --> off
-httpd_dbus_avahi --> on
+httpd_dbus_avahi --> off
 httpd_dbus_sssd --> off
 httpd_dontaudit_search_dirs --> off
 httpd_enable_cgi --> on
 httpd_enable_ftp_server --> off
 httpd_enable_homedirs --> off
 httpd_execmem --> off
-httpd_graceful_shutdown --> off
+httpd_graceful_shutdown --> on
 httpd_manage_ipa --> off
 httpd_mod_auth_ntlm_winbind --> off
 httpd_mod_auth_pam --> off
@@ -57,58 +122,195 @@
 httpd_use_openstack --> off
 httpd_use_sasl --> off
 httpd_verify_dns --> off
-kerberos_enabled --> off
+icecast_use_any_tcp_ports --> off
+irc_use_any_tcp_ports --> off
+irssi_use_full_network --> off
+kdumpgui_run_bootloader --> off
+keepalived_connect_any --> off
+kerberos_enabled --> on
+ksmtuned_use_cifs --> off
+ksmtuned_use_nfs --> off
 logadm_exec_content --> on
 logging_syslogd_can_sendmail --> off
 logging_syslogd_run_nagios_plugins --> off
 logging_syslogd_use_tty --> on
 login_console_enabled --> on
+logrotate_read_inside_containers --> off
+logrotate_use_nfs --> off
+logwatch_can_network_connect_mail --> off
+lsmd_plugin_connect_any --> off
+mailman_use_fusefs --> off
+mcelog_client --> off
+mcelog_exec_scripts --> on
+mcelog_foreground --> off
+mcelog_server --> off
+minidlna_read_generic_user_content --> off
 mmap_low_allowed --> off
-mount_anyfile --> off
+mock_enable_homedirs --> off
+mount_anyfile --> on
+mozilla_plugin_bind_unreserved_ports --> off
+mozilla_plugin_can_network_connect --> off
+mozilla_plugin_use_bluejeans --> off
+mozilla_plugin_use_gps --> off
+mozilla_plugin_use_spice --> off
+mozilla_read_content --> off
+mpd_enable_homedirs --> off
+mpd_use_cifs --> off
+mpd_use_nfs --> off
+mplayer_execstack --> off
+mysql_connect_any --> off
+nagios_run_pnp4nagios --> off
+nagios_run_sudo --> off
+nagios_use_nfs --> off
+named_tcp_bind_http_port --> off
+named_write_master_zones --> off
+neutron_can_network --> off
 nfs_export_all_ro --> on
 nfs_export_all_rw --> on
+nfsd_anon_write --> off
 nis_enabled --> off
+nscd_use_shm --> on
+openshift_use_nfs --> off
+openvpn_can_network_connect --> on
+openvpn_enable_homedirs --> on
+openvpn_run_unconfined --> off
+pcp_bind_all_unreserved_ports --> off
+pcp_read_generic_logs --> off
+piranha_lvs_can_network_connect --> off
+polipo_connect_all_unreserved --> off
+polipo_session_bind_all_unreserved_ports --> off
+polipo_session_users --> off
+polipo_use_cifs --> off
+polipo_use_nfs --> off
 polyinstantiation_enabled --> off
+postfix_local_write_mail_spool --> on
 postgresql_can_rsync --> off
 postgresql_selinux_transmit_client_label --> off
 postgresql_selinux_unconfined_dbadm --> on
 postgresql_selinux_users_ddl --> on
+pppd_can_insmod --> off
+pppd_for_user --> off
+privoxy_connect_any --> on
+prosody_bind_http_port --> off
+puppetagent_manage_all_files --> off
+puppetmaster_use_db --> off
 racoon_read_shadow --> off
+radius_use_jit --> off
+redis_enable_notify --> off
+rpcd_use_fusefs --> off
+rsync_anon_write --> off
+rsync_client --> off
+rsync_export_all_ro --> off
+rsync_full_access --> off
+samba_create_home_dirs --> off
+samba_domain_controller --> off
+samba_enable_home_dirs --> off
+samba_export_all_ro --> off
+samba_export_all_rw --> off
+samba_load_libgfapi --> off
+samba_portmapper --> off
+samba_run_unconfined --> off
+samba_share_fusefs --> off
+samba_share_nfs --> off
+sanlock_enable_home_dirs --> off
+sanlock_use_fusefs --> off
+sanlock_use_nfs --> off
+sanlock_use_samba --> off
+saslauthd_read_shadow --> off
 secadm_exec_content --> on
 secure_mode --> off
 secure_mode_insmod --> off
 secure_mode_policyload --> off
-selinuxuser_direct_dri_enabled --> off
+selinuxuser_direct_dri_enabled --> on
 selinuxuser_execheap --> off
-selinuxuser_execmod --> off
-selinuxuser_execstack --> off
+selinuxuser_execmod --> on
+selinuxuser_execstack --> on
 selinuxuser_mysql_connect_enabled --> off
-selinuxuser_ping --> off
+selinuxuser_ping --> on
 selinuxuser_postgresql_connect_enabled --> off
-selinuxuser_rw_noexattrfile --> off
+selinuxuser_rw_noexattrfile --> on
 selinuxuser_share_music --> off
 selinuxuser_tcp_server --> off
 selinuxuser_udp_server --> off
 selinuxuser_use_ssh_chroot --> off
+sge_domain_can_network_connect --> off
+sge_use_nfs --> off
+smartmon_3ware --> off
+smbd_anon_write --> off
+spamassassin_can_network --> off
+spamd_enable_home_dirs --> on
+spamd_update_can_network --> off
+squid_connect_any --> on
+squid_use_tproxy --> off
 ssh_chroot_rw_homedirs --> off
 ssh_keysign --> off
 ssh_sysadm_login --> off
 staff_exec_content --> on
 staff_use_svirt --> off
+swift_can_network --> off
 sysadm_exec_content --> on
-unconfined_chrome_sandbox_transition --> off
+telepathy_connect_all_ports --> off
+telepathy_tcp_connect_generic_network_ports --> on
+tftp_anon_write --> off
+tftp_home_dir --> off
+tmpreaper_use_cifs --> off
+tmpreaper_use_nfs --> off
+tmpreaper_use_samba --> off
+tomcat_can_network_connect_db --> off
+tomcat_read_rpm_db --> off
+tomcat_use_execmem --> off
+tor_bind_all_unreserved_ports --> off
+tor_can_network_relay --> off
+unconfined_chrome_sandbox_transition --> on
 unconfined_login --> on
-unconfined_mozilla_plugin_transition --> off
+unconfined_mozilla_plugin_transition --> on
 unprivuser_use_svirt --> off
 use_ecryptfs_home_dirs --> off
 use_fusefs_home_dirs --> off
-use_nfs_home_dirs --> on
+use_lpd_server --> off
+use_nfs_home_dirs --> off
 use_samba_home_dirs --> off
 user_exec_content --> on
+varnishd_connect_any --> off
+virt_read_qemu_ga_data --> off
+virt_rw_qemu_ga_data --> off
+virt_sandbox_use_all_caps --> on
+virt_sandbox_use_audit --> on
+virt_sandbox_use_fusefs --> off
+virt_sandbox_use_mknod --> off
+virt_sandbox_use_netlink --> off
+virt_sandbox_use_sys_admin --> off
+virt_transition_userdomain --> off
+virt_use_comm --> off
+virt_use_execmem --> off
+virt_use_fusefs --> off
+virt_use_glusterd --> off
+virt_use_nfs --> off
+virt_use_rawip --> off
+virt_use_samba --> off
+virt_use_sanlock --> off
+virt_use_usb --> on
+virt_use_xserver --> off
+webadm_manage_user_files --> off
+webadm_read_user_files --> off
+wine_mmap_zero_ignore --> off
 xdm_bind_vnc_tcp_port --> off
 xdm_exec_bootloader --> off
 xdm_sysadm_login --> off
 xdm_write_home --> off
+xen_use_nfs --> off
+xend_run_blktap --> on
+xend_run_qemu --> on
+xguest_connect_network --> on
+xguest_exec_content --> on
+xguest_mount_media --> on
+xguest_use_bluetooth --> on
 xserver_clients_write_xshm --> off
 xserver_execmem --> off
 xserver_object_manager --> off
+zabbix_can_network --> off
+zabbix_run_sudo --> off
+zarafa_setrlimit --> off
+zebra_write_config --> off
+zoneminder_anon_write --> off
+zoneminder_run_sudo --> off

参考にしたもの

www.slideshare.net

milestone-of-se.nesuke.com

www.shoeisha.co.jp

milestone-of-se.nesuke.com

CentOS 7 : SELinux : ポリシータイプの設定 : Server World

Apacheで403 Forbiddenが表示された時のチェックポイント5選 | Wedding Park CREATORS Blog

*1:プロセスに付与するラベルはタイプではなくドメインと呼ぶ。

*2:そのため、Booleanとも呼ぶ。

*3:書き換え前に確認するのを忘れてしまった……。

LVM

LVMとは

LVM(Logical Volume Manager)とは、複数のパーティションにまたがったストレージをまとめ、仮想的(論理的)なストレージを提供するソフトウェアのこと。

LVMにより、複数のストレージを1つのストレージに見せかけたり、仮想的なストレージプールから一定の容量分を切り出して使うことができる。LVMがない場合、OSからは物理的なパーティションが直接ストレージとして見えていることになるが、容量の増減を動的に行うことができない*1

LVMの構成要素

LVMには物理ボリューム、ボリュームグループ、論理ボリュームという3つの構成要素がある。 前の節ではLVMの用語を使わずに説明したが、これらの用語を用いてLVMを改めて定義すると以下のようになる。

LVMとは、複数の物理ボリュームをボリュームグループとしてまとめ、論理ボリュームを提供するソフトウェアのこと。

物理ボリューム(PV)

LVMにおける物理ボリュームとは物理的なパーティションのこと。Linuxではパーティションに対応するデバイスファイルはudevによって作成されているが、LVMを利用する場合は改めて物理ボリュームというエンティティを定義する必要がある*2

物理ボリュームの操作にはpvcreate等のpvが接頭につくコマンドを用いる。

物理エクステント(PE)

似たような言葉に物理エクステントがあるので触れておく。LVMが扱う記憶の最小管理単位である。言い換えると、物理ボリュームは物理エクステントの集合体である。PEのサイズは8KB~512MBの範囲で指定が可能である。

ボリュームグループ(VG)

ボリュームグループとは物理ボリュームをまとめたもの。仮想的に一つの大きなボリューム(ストレージ)を作っていると見なせる。特定のボリュームグループに対し、異なるハードディスクに属するパーティションが所属していても問題ない。

ボリュームグループの操作にはvgcreate等のvgが接頭につくコマンドを用いる。

論理ボリューム(LV)

ボリュームグループから特定容量分をストレージとして切り出したものである。ボリュームグループに対するパーティションのようなものと考えてもよい。LVMでは論理ボリュームが実ファイルを格納する領域となっており、ファイルシステムが構成されるストレージデバイスとなる。論理ボリュームは動的にサイズの伸縮が可能である。

以下の例では、sda5パーティションの中にcl-*というLVMが構成されていることがわかる。例えば/はXFSという種類のファイルシステムであり、対応するデバイスファイルは/dev/mapper/cl-rootということが見て取れる*3

[root@nuc-centos8 ~]# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0   1.8T  0 disk
|(省略)
`-sda5            8:5    0   1.1T  0 part
  |-cl-root     253:0    0    50G  0 lvm  /
  |-cl-swap     253:2    0  15.7G  0 lvm  [SWAP]
  |-cl-usr      253:3    0   250G  0 lvm  /usr
  |-cl-home     253:5    0   250G  0 lvm  /home
  |-cl-var      253:7    0   300G  0 lvm  /var
  `-cl-opt      253:10   0   300G  0 lvm  /opt
[root@nuc-centos8 ~]# df -T -h
Filesystem                     Type      Size  Used Avail Use% Mounted on
devtmpfs                       devtmpfs   16G     0   16G   0% /dev
tmpfs                          tmpfs      16G     0   16G   0% /dev/shm
tmpfs                          tmpfs      16G  242M   16G   2% /run
tmpfs                          tmpfs      16G     0   16G   0% /sys/fs/cgroup
/dev/mapper/cl-root            xfs        50G  431M   50G   1% /
/dev/mapper/cl-usr             xfs       250G  4.0G  246G   2% /usr
/dev/mapper/cl-var             xfs       300G   23G  278G   8% /var
/dev/mapper/cl-opt             xfs       300G  9.8G  291G   4% /opt
/dev/mapper/cl-home            xfs       250G  1.8G  249G   1% /home
/dev/sda4                      ext4      976M  144M  766M  16% /boot
/dev/sda1                      vfat      200M   12M  188M   6% /boot/efi
192.168.0.11:/volume1/document nfs       3.6T  922G  2.7T  26% /mnt/synology/document
192.168.0.11:/volume1/download nfs       3.6T  922G  2.7T  26% /mnt/synology/download
tmpfs                          tmpfs     3.2G     0  3.2G   0% /run/user/0

論理ボリュームの操作にはlvcreate等のlvが接頭につくコマンドを用いる。

まとめ

LVMの構成要素の関係を表す図を以下に引用する。

https://i2.wp.com/www.pmi-sfbac.org/wp-content/uploads/2021/06/linux-lvm-vg.png?w=589&ssl=1 【Linuxの基礎知識】LVMとは?LVMを理解しよう! | Beエンジニアより引用

関連記事

tanke25616429.hatenablog.com

tanke25616429.hatenablog.com

参考にしたもの

www.idcf.jp

13.5. fdisk を使用したパーティションのサイズ変更 Red Hat Enterprise Linux 7 | Red Hat Customer Portal

【 vgcreate 】コマンド――ボリュームグループを作成する:Linux基本コマンドTips(336) - @IT

IBM Knowledge Center

www.pmi-sfbac.org

LVMってそもそもなんなのさ!?:ぴろにっき:SSブログ

IT技術者なら知っておきたい ストレージの原則と技術 | EMC Education Services, 株式会社クイープ |本 | 通販 | Amazon

*1:厳密にはそのディスクの最後のパーティションはサイズを変更できる。ちなみに、Red HatではLVMのパーティションのサイズ変更のみサポートする。

*2:後述するボリュームグループを構成する際に、物理ボリュームを作成していないパーティションを直接メンバーとして指定することはできない。

*3:バイスマッパーについては別途記事を作成予定。

ストレージをLinuxから利用する方法

本記事では、Linuxがコンピュータに接続されたHDD/SSD等のストレージ(記憶領域)に読み書きできるようになるまでの流れを整理する。iSCSI等のストレージプロトコルや、NFSなどのリモートストレージなどの内容には触れない。

ストレージをLinuxから利用するまでのステップ

HDDやSSD等のストレージをLinux上から利用するためには、ストレージを物理的にシステムに接続してからいくつか以下のステップを踏む必要がある*1

  1. パーティションを切る
  2. パーティションをフォーマットし、ファイルシステムを作る
  3. 作ったファイルシステムをマウントする

パーティションとは

パーティションとはストレージを論理的に分割した際のここの領域のことである*2。ディスク全体をひとつの領域とする場合にも、全容量を割り当てたひとつのパーティションを作る必要がある(下部の「補足:ストレージ全体を一つの領域とした場合」も参照のこと)。

lsblkコマンドでパーティションの種類を確認することができる。デバイスsdaはディスク装置で、sda1やsda2はパーティションであることが確認できる。

[root@nuc-centos8 ~]# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0   1.8T  0 disk
|-sda1            8:1    0   200M  0 part /boot/efi
|-sda2            8:2    0     1G  0 part
(省略)

パーティションに関する操作(作成、変更等)には fdisk というコマンドが利用できる。

フォーマットとは

フォーマットとは、ファイルシステムの種類に合わせて記憶領域を構造化することである*3

パーティションはただの領域であり、それだけではデータの読み書きに利用することができない。 パーティションファイルシステムで「フォーマット」することで、ファイルを単位としたデータの管理が行えるようになる。 この操作にはファイルシステムを作成するコマンドが用意されているので(mkfs等)、それを利用する。

マウントとは

抽象的な定義としては、コンピュータに接続したストレージをOS等のソフトウェアに認識させ、読み書き可能な状態にすることを指す。より具体的には、ストレージ上のファイルの読み書きをルートファイルシステム上のアクセス可能な位置に配置し統合することである。

下図のようにフォーマット済みのファイルシステムをルートファイルシステム(=システムのファイルシステム)に統合する。この図ではすでにストレージ上にデータがある場合を書いているが、まっさらなストレージをマウントするケースも同じである。また、種類の違うファイルシステムでもマウント可能である。

f:id:tanke25616429:20210212013300p:plain
ファイルシステムのマウント

マウント操作には mount コマンドを使う。マウントを解除する場合はアンマウント(umountコマンド)を利用する。

まとめ

ストレージをLinuxから利用するにはパーティションを切り(fdisk)、何らかのファイルシステムでフォーマットし(mkfs)、マウントする(mount)というステップが必要である。 コマンドの流れだけ書くと、fdisk → mkfs → mountとなる。

補足:ストレージ全体を一つの領域とした場合

あえて、ストレージ全体を一つの領域とする(/bootやswap領域も分けない)ようにインストールを行っても、自動でパーティションが構成されていることがわかる。ルートファイルシステム/は1つのパーティションになっているが、対応するデバイスsda1はパーティションである(分割前のsdaではない)。

f:id:tanke25616429:20210212004338p:plain
パーティション分割をしないでインストールしたシステム

関連記事

tanke25616429.hatenablog.com tanke25616429.hatenablog.com tanke25616429.hatenablog.com

参考にしたもの

パーティション - Wikipedia hnavi.co.jp eng-entrance.com e-words.jp qiita.com

kapibara-sos.net

Linux - ファイルシステムのマウントとアンマウント Linux - パーティションとファイルシステムの作成 Ping-t LPIC/LinuC Lv2-201(Ver4.5) Linuxファイルシステムの操作と保守

*1:厳密には、1.の前にハードウェアをシステムから認識できる状態にするステップが入る。Linuxではデバイスもファイルとして扱うことができるが、デバイスファイルはudevによって生成される。関連記事:udev - Knのアウトプットを参照のこと。

*2:パーティションを作成する形式としては、MBRとGPTの2つの形式がある。

*3:ブートブロック、スーパーブロック、inodeブロック、データブロックに区切られる。

LinuxでWi-Fi接続をブリッジできるか?

やりたかったことと結果

ちゃんと調べたことというより、雑多なメモ。

家のラボ環境でWi-Fi接続している物理サーバがあるが、その中にKVMで立てたVMをブリッジ接続で家のLANに接続したかった。サーバは有線のインタフェースももちろんあるのだが、これは別のネットワークにつなぎたかったため、管理用には家のWi-Fi経由でつなぐのが望ましかった。

f:id:tanke25616429:20210124231950p:plain
やりたかった構成

KVMのブリッジ接続の手順を参考にやってみたが、うまくいかない。

Wi-Fi接続のコネクションをブリッジインタフェースに接続できるか?

結論から言うとできなさそうである。

アドホック または インフラストラクチャー モードで稼働している Wi-Fi ネットワーク上では、ブリッジは確立できないことに注意してください。IEEE 802.11 標準が、通信時間の効率性のために Wi-Fi で 3 アドレスフレームの使用を指定するためです。 access.redhat.com

上記文章だけ見るとアドホック または インフラストラクチャー モード「以外」であればブリッジ接続できそうに見えるが、Wi-Fiは基本的にいずれかのモードになるようである。

ワイヤレスネットワークは、インフラストラクチャーモードまたはアドホックモードのいずれかで動作可能です。 www.konicaminolta.jp

ということで、Wi-Fi接続で物理ホストがネットワークにつながっている場合、KVMゲストはブリッジ接続では当該ネットワークに接続不可となる。NATを使う、ホストをルーター化してルーティングを書く、といった対応が必要である。

LinuxにおけるIPフォワーディング

概要

LinuxにはIPパケットをフォワーディングする機能が具備されている。IPフォワーディングはあるネットワークから受け取ったパケットを別のネットワークに転送する技術である。言い換えると、2つのNICの間でパケットを転送する技術である。これにより、パケットが異なるネットワークの間を往き来できるようになる*1

LinuxでIPフォワードを有効にするには、カーネルパラメータ net.ipv4.ip_forwardの値を1にする必要がある(設定方法は過去エントリを参照 カーネルパラメータの設定方法(CentOS 8) - Knのアウトプット)。 カーネルパラメータを設定した段階では2つのNIC間でパケットが転送できるようになっただけで、適切な通信が行われるようになったわけではない。実際にフォワーディングされるためにはルーティングテーブルを適切に設定する必要がある。

設定例

サーバーA、B、Cの3台があり、Bに対しフォワーディングの設定を行う。 Bは2つのネットワーク、192.168.0.0/24192.168.122.0/24に所属している。

[root@nuc-centos8 ~]# ip a
(略)
4: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0c:7a:15:da:07:37 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.14/24 brd 192.168.0.255 scope global dynamic noprefixroute wlp0s20f3
(略)
5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:54:00:9c:81:ac brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
(略)

サーバAは192.168.0.0/24のみに所属している。

[root@virtualbox-centos7 ~]# ip a
(略)
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:08:35:9c brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.92/24 brd 192.168.0.255 scope global noprefixroute enp0s8
(略)

サーバCは192.168.122.0/24のみに所属している。

[root@kvm-centos8 ~]# ip a
(略)
2: ens2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:34:01:09 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.100/24 brd 192.168.122.255 scope global noprefixroute ens2
(略)

サーバAからサーバCへpingを打つ。このときサーバBでIPフォワーディングが有効になっており、ルーティングテーブルが設定されていればpingは到達する。 なお、サーバAからサーバBにパケットが飛ぶようにするため、サーバAのデフォルトゲートウェイはサーバBのIPアドレスにしてある。

[root@virtualbox-centos7 ~]# nmcli con show enp0s8
(略)
ipv4.addresses:                         192.168.0.92/24
ipv4.gateway:                           192.168.0.14
(略)

サーバBではすでにIPフォワーディングが有効( net.ipv4.ip_forward = 1)で、ルーティングテーブルも設定済みである*2

[root@nuc-centos8 ~]# sysctl -a | grep net.ipv4.ip.forward
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_update_priority = 1
net.ipv4.ip_forward_use_pmtu = 0
[root@nuc-centos8 ~]# ip r
default via 192.168.0.1 dev wlp0s20f3 proto dhcp metric 600
192.168.0.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.0.100 metric 600
192.168.0.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.0.14 metric 600
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

サーバAからpingを打つ。応答が返ってきていることがわかる。

[root@virtualbox-centos7 ~]# ping 192.168.122.100
PING 192.168.122.100 (192.168.122.100) 56(84) bytes of data.
64 bytes from 192.168.122.100: icmp_seq=1 ttl=63 time=106 ms
64 bytes from 192.168.122.100: icmp_seq=2 ttl=63 time=22.9 ms
64 bytes from 192.168.122.100: icmp_seq=3 ttl=63 time=41.1 ms
(略)

pingを打ちっぱなしのままサーバCでtcpdumpを使いパケットを監視してみると、ICMPのrequestが飛んできている。

[root@kvm-centos8 ~]# tcpdump -i any src host 192.168.0.92 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:07:47.686403 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 57, length 64
11:07:48.710472 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 58, length 64
11:07:49.734488 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 59, length 64
11:07:50.656000 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 60, length 64
(略)

pingtcpdumpを仕掛けたまま、サーバB上でIPフォワーディングを無効化してみる。一時的に無効化するにはファイル/proc/sys/net/ipv4/ip_forwardの値を直接0に書き換える。

[root@nuc-centos8 ~]# echo 0 > /proc/sys/net/ipv4/ip_forward

サーバAのping応答が止まる。

(略)
64 bytes from 192.168.122.100: icmp_seq=126 ttl=63 time=98.5 ms
64 bytes from 192.168.122.100: icmp_seq=127 ttl=63 time=117 ms
(ここで止まる)

サーバCでもtcpdumpの更新が止まる。

(略)
11:11:26.734165 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2748, seq 126, length 64
11:11:27.757086 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2748, seq 127, length 64
(ここで止まる)

サーバB上でIPフォワーディングを再び有効にするとpingの応答が返り、tcpdumpの更新が再開される(応答が返ってきている様子等は割愛する)。

[root@nuc-centos8 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

参考にしたもの

IPフォワード(IP Forward) | Linux技術者認定 LinuC | LPI-Japan

xtech.nikkei.com

*1:フォワーディングとルーティングは厳密には区別される。ルーティングは転送先の経路を選択すること、フォワーディングは実際に転送することである。ただし、ルーティングといった場合に経路選択と転送をまとめて呼ぶケースもあるので、文脈に応じて読み取る必要がある。

*2:192.168.0.100はネットワークデバイスNIC)wlp0s20f3に振ったセカンダリIPアドレスであり、今回の実験には関係ないので無視してよい。