ITエンジニアのコツコツ日記

ITエンジニアの雑記です

SoftetherVPN のSecureNATの動きが怪しい

SoftetherVPNのSecureNAT

SoftetherVPNのSecureNATは仮想HUB内に仮想のルータを配置する機能。

f:id:itkotsukotsu:20201013232617p:plain

SecureNATはDHCPサーバ機能もあり、標準では192.168.30.0/24のネットワークを作成する。

f:id:itkotsukotsu:20201013233536p:plain

SecureNATを有効にするとSoftetherが動作するホストを通じて外部への通信が可能。

気を付けないのがSecureNATを有効にしている仮想HUBとローカルブリッジは一切関係ない。

SecureNATが生成するゲートウェイSoftetherホスト自体であり、ローカルブリッジのNICとは関係なく、Softetherホストの持つ経路情報によって通信が提供される。

つまり、Softetherホストがインターネット接続可能であればSecureNAT上のホストはインターネット接続が可能になるし、Softetherホストが複数NICを持ち、別のLANへのルーティング情報を持っていればそこへもつながる。

ネット上のブログや記事はSecureNATの本質を捉え間違えているものが多いので注意が必要だ。

SecureNATの動きが怪しい

さくらのVPS上のCentOS7Softetherをインストールして動作検証を行ったが、VPNを接続した後の数秒後(10秒程度)くらいに通信が途絶えてしまう。

要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。  ←ここでSecureNATを有効に
192.168.100.21 からの応答: バイト数 =32 時間 =34ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =33ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =46ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =53ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =52ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =34ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =62ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =40ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =41ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =28ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =46ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =56ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =44ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =55ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =64ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =50ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =51ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =41ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =32ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =51ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =53ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =46ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =42ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =35ms TTL=63
192.168.100.21 からの応答: バイト数 =32 時間 =33ms TTL=63
要求がタイムアウトしました。    ← なぜか通信できなくなる。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。

通信が途切れた際のSecureNATのステータスをモニタすると、カーネルモード NAT で動作中Raw IPモードで動作中はいになったとたんに接続が切れたことが分かった。

このSecureNATは動作モードがあり、「ユーザーモード」と「カーネルモード」と「Raw IP モード」があるらしい。

公式 SecureNATカーネルモードについて

ユーザーモード NAT

ユーザーモードNATは特権を必要としない一般プロセスでNAT処理を実現するもの。

このため、Linuxカーネルの機能を使えないためオーバーヘッドが大きく、パフォーマンスが低い。

IPtablesも使わないため、影響範囲は狭くほぼ動作する。

カーネルモードNAT

以下公式より引用

一般的な NAT 処理と同様にパケットの内容の解釈を行わずにヘッダの書き換えのみで動作するため、ユーザーモード SecureNAT と比較して高速に動作します。

インターフェースレベルの低レベルAPI経由でヘッダのみの書き換えで動作するモード。これは上位の権限を要求する場合があるそうだ。

Raw IP モードNAT

最後はいわゆる普通のNATを行うモードで、iptables経由でLinuxのNetfilterのnat機能を使う。

Linux Kernel のモジュールで動作するので非常に高速に動作する。

問題は利用モードの自動選択

どうも利用可能かどうかを自動判定して、適切なモードを選択してくれる仕様のようだ。

イーサネットインターフェイスでの通信に成功した場合はカーネルモード SecureNAT が使用され、Raw IP ソケットでの通信に成功した場合は Raw IP モード SecureNAT が使用されます。いずれも成功しなかった場合はユーザモード SecureNAT が使用されます。

方式ドキュメントを読む限り、ユーザモードNATからスタートして、カーネルモードの可否、RawIPモードの可否を判定するようだ。

ユーザモードNAT ⇒ カーネルモードNAT ⇒ RawIPモードNAT

この方針はいいが、なぜかエラーとなるカーネルモードとRawIPモードが有効になってしまった。

原因はDocker?

今回はCentOS7上でDockerを用いてSoftetherを動作させていた。

低レベルのネットワークアクセスのため、network driverはhostで、privilegedな権限を付与して動作させている。

ここの設定はおそらく問題ないが、いけなかったのはDockerがiptables経由でnatテーブル等を書き換えていること。

softetherが設定したnatテーブルを不当に書き戻している可能性が高い。

ホストのiptablesを操作するプロセスが共存するのはあまり好ましくないだろう。

対策はユーザモードNAT固定

幸いにも NATの利用モードの明示的な指定が可能だ。

カーネルモードを禁止する場合は「DisableKernelModeSecureNAT」を、Raw IP モードを禁止する場合は「DisableRawIpModeSecureNAT」を、ユーザモードを禁止する場合は「DisableUserModeSecureNAT」を、それぞれ 「1」に設定して下さい。 公式: 利用モードの選択

※ 公式ページのDisableRawIpModeSecureNATDisableIpRawModeSecureNATのタイポです。

以下を設定すればユーザモードで固定することが可能だ。

  • DisableKernelModeSecureNAT: 1
  • DisableIpRawModeSecureNAT: 1

上記を仮想HUBのプロパティから設定すれば問題なく動作するはずだ。

Firewalldの初期設定をiptablesから読み解いてみる

Firewalldとは

f:id:itkotsukotsu:20201010172106p:plain:w400

FirewalldはRedhat Enterprise Linux 7 (RHEL7)系から主流となったパケットフィルタツールだ。

firewalldはiptablesを経由してLinuxカーネルのNetfilterを操作するフロントエンドツールであるため、firewalldがどのようなiptables設定を施すか把握すると良い。

iptablesの使い方についてこの記事を読んでほしい。

Firewalld有効時のiptables

firewalldのサービスが停止した状態のiptablesは以下。

チェインとしてINPUT, OUTPUT, FORWARDがあり、特に何もエントリが無い。

[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

ここでfirewalldを有効にする。

firewalldの設定は以下で標準設定のままだ。

なお、NICは3つありens160, ens192, ens224がある。

[root@localhost ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no        
  interfaces: ens160 ens192 ens224
  sources:
  services: dhcpv6-client ssh     
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

firewalldのサービス有効時のiptablesは以下。 非常にチェインとエントリが多い。

[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED     
ACCEPT     all  --  anywhere             anywhere
INPUT_direct  all  --  anywhere             anywhere
INPUT_ZONES_SOURCE  all  --  anywhere             anywhere
INPUT_ZONES  all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED     
ACCEPT     all  --  anywhere             anywhere
FORWARD_direct  all  --  anywhere             anywhere
FORWARD_IN_ZONES_SOURCE  all  --  anywhere             anywhere
FORWARD_IN_ZONES  all  --  anywhere             anywhere
FORWARD_OUT_ZONES_SOURCE  all  --  anywhere             anywhere
FORWARD_OUT_ZONES  all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
OUTPUT_direct  all  --  anywhere             anywhere

Chain FORWARD_IN_ZONES (1 references)
target     prot opt source               destination
FWDI_public  all  --  anywhere             anywhere            [goto]
FWDI_public  all  --  anywhere             anywhere            [goto]
FWDI_public  all  --  anywhere             anywhere            [goto]
FWDI_public  all  --  anywhere             anywhere            [goto]

Chain FORWARD_IN_ZONES_SOURCE (1 references)
target     prot opt source               destination

Chain FORWARD_OUT_ZONES (1 references)
target     prot opt source               destination
FWDO_public  all  --  anywhere             anywhere            [goto]
FWDO_public  all  --  anywhere             anywhere            [goto]
FWDO_public  all  --  anywhere             anywhere            [goto]
FWDO_public  all  --  anywhere             anywhere            [goto]

Chain FORWARD_OUT_ZONES_SOURCE (1 references)
target     prot opt source               destination

Chain FORWARD_direct (1 references)
target     prot opt source               destination

Chain FWDI_public (4 references)
target     prot opt source               destination
FWDI_public_log  all  --  anywhere             anywhere
FWDI_public_deny  all  --  anywhere             anywhere
FWDI_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

Chain FWDI_public_allow (1 references)
target     prot opt source               destination

Chain FWDI_public_deny (1 references)
target     prot opt source               destination

Chain FWDI_public_log (1 references)
target     prot opt source               destination

Chain FWDO_public (4 references)
target     prot opt source               destination
FWDO_public_log  all  --  anywhere             anywhere
FWDO_public_deny  all  --  anywhere             anywhere
FWDO_public_allow  all  --  anywhere             anywhere

Chain FWDO_public_allow (1 references)
target     prot opt source               destination

Chain FWDO_public_deny (1 references)
target     prot opt source               destination

Chain FWDO_public_log (1 references)
target     prot opt source               destination

Chain INPUT_ZONES (1 references)
target     prot opt source               destination
IN_public  all  --  anywhere             anywhere            [goto]
IN_public  all  --  anywhere             anywhere            [goto]
IN_public  all  --  anywhere             anywhere            [goto]
IN_public  all  --  anywhere             anywhere            [goto]

Chain INPUT_ZONES_SOURCE (1 references)
target     prot opt source               destination

Chain INPUT_direct (1 references)
target     prot opt source               destination

Chain IN_public (4 references)
target     prot opt source               destination
IN_public_log  all  --  anywhere             anywhere
IN_public_deny  all  --  anywhere             anywhere
IN_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

Chain IN_public_allow (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW,UNTRACKED

Chain IN_public_deny (1 references)
target     prot opt source               destination

Chain IN_public_log (1 references)
target     prot opt source               destination

Chain OUTPUT_direct (1 references)
target     prot opt source               destination

一つ一つ読み解いていこう。

Firewalldのチェイン

Firewalld有効時のiptablesのチェイン一覧は以下だ。

[root@localhost ~]# iptables -L -n --line-number | grep Chain
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)
Chain FORWARD_IN_ZONES (1 references)
Chain FORWARD_IN_ZONES_SOURCE (1 references)
Chain FORWARD_OUT_ZONES (1 references)
Chain FORWARD_OUT_ZONES_SOURCE (1 references)
Chain FORWARD_direct (1 references)
Chain FWDI_public (4 references)
Chain FWDI_public_allow (1 references)
Chain FWDI_public_deny (1 references)
Chain FWDI_public_log (1 references)
Chain FWDO_public (4 references)
Chain FWDO_public_allow (1 references)
Chain FWDO_public_deny (1 references)
Chain FWDO_public_log (1 references)
Chain INPUT_ZONES (1 references)
Chain INPUT_ZONES_SOURCE (1 references)
Chain INPUT_direct (1 references)
Chain IN_public (4 references)
Chain IN_public_allow (1 references)
Chain IN_public_deny (1 references)
Chain IN_public_log (1 references)
Chain OUTPUT_direct (1 references)

ビルドインチェインとなるINPUT, FORWARD, OUTPUTがあり、それ以降はユーザ定義チェインとなる。

非常に多くのユーザ定義チェインがあり、Firewalldの設計思想に合わせたエントリの分類ができるようになっている。

ビルドインチェイン

ビルドインチェインの例としてINPUTを見てみよう。

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED     
ACCEPT     all  --  anywhere             anywhere
INPUT_direct  all  --  anywhere             anywhere
INPUT_ZONES_SOURCE  all  --  anywhere             anywhere
INPUT_ZONES  all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

ACCEPTですべての通信を許可するエントリがあり、そのあとにtargetがINPUT_direct, INPUT_ZONES_SOURCE, INPUT_ZONESがある。

これらはユーザ定義チェインであり、ビルドインチェインであるINPUTにエントリがあり、呼び出される。

Firewalldにはゾーンの考え方があり、ゾーン毎にチェインを作成している。

各ユーザ定義チェインの呼び出し順はビルドインチェインのこのINPUTを見ればわかる。

ユーザ定義チェイン

Firewalldはユーザ定義チェインを作成し、ビルドインチェインにエントリを追加してFirewalldの設定を施している。

例として、INTPUTチェインに含まれるINPUT_directを見てみよう。

Chain INPUT_direct (1 references)
target     prot opt source               destination

1 referencesとなっており、参照をもつユーザ定義チェインであることが分かる。

特にエントリはないがfirewalld が作成するINPUT_directに分類するエントリが定義される。

Firewalldの初期設定の動き

ビルドインチェインエントリのユーザ定義チェインの動きを追って、Firewalldの設定を読み解いてみる。

Firewalld上の設定

Firewalld上の設定は以下だ。(※再掲)

  • target: defaultで基本動作はREJECT(DROP)
  • 3つのインターフェース(NIC)向けに設定
  • icmpは許可(ping通信等)
  • ssh許可
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160 ens192 ens224
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

iptables上の設定

このFirewalldの動きを実現するiptablesの記述がされていれば良いことになる。 それぞれ該当するものがあるか確認する。

パケットのデフォルト動作は破棄

Chain INPUT (policy ACCEPT)
...
...
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

INPUTチェインにDROPREJECTのエントリがある。

REJECTはICMPのエラーを返すようにしている。

これらのエントリでINPUTのACCEPTに受理されなかったのは破棄される。

3つのインターフェース(NIC)向けに設定

ユーザ定義チェインに インタフェースオプションを指定して各NICに対して設定が適用されるようになっていることが読み取れる。

# iptables --list-rules
...
...
-A FORWARD_IN_ZONES -i ens224 -g FWDI_public
-A FORWARD_IN_ZONES -i ens192 -g FWDI_public
-A FORWARD_IN_ZONES -i ens160 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
Chain FORWARD_IN_ZONES (1 references)
target     prot opt source               destination
FWDI_public  all  --  anywhere             anywhere            [goto]
Chain FWDI_public (4 references)   ←3NIC分追加されている
target     prot opt source               destination
FWDI_public_log  all  --  anywhere             anywhere
FWDI_public_deny  all  --  anywhere             anywhere
FWDI_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

icmpは許可(ping通信等)

NICが参照するチェインFWDI_publicにてACCEPT icmpが記述されている。

Chain FWDI_public (4 references)
target     prot opt source               destination
FWDI_public_log  all  --  anywhere             anywhere
FWDI_public_deny  all  --  anywhere             anywhere
FWDI_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

ssh許可

ユーザ定義チェインのIN_public_allowtcp dpt:sshが許可されている。

Chain IN_public_allow (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW,UNTRACKED

まとめ

firewalldはzone管理等やりたい設定をするには使いやすいフロントエンドのパケットフィルタツールだ。

しかし実態としてはiptablesを操作しており、firewalldで実現したいiptablesの設定がされている。

Dockerやkubnerenes等はiptablesを操作して内部仮想ネットワークを構築しており、多数のツールによってiptablesが設定されるため想定外の動きをする時がある。

疎通が取れない等で問題を切り分けするならiprablesを読み解くのが一番正確だろう。

Google Search Consoleではてなブログのサイトマップが登録されるようになった(2020)

サイトマップが登録されるようになった

f:id:itkotsukotsu:20201009123322p:plain

Google Search Consoleはてなブログサイトマップが登録されないことはわりと有名な問題だった。

何をしても登録されない。

独自ドメインで運用している人は登録されているサイトもあったようだが、無料ブログはblog.hatena.ne.jpで始まるせいか、まったくと言っていいほど登録できる気配がなかった。

変化があったのは2020年9月22日

f:id:itkotsukotsu:20201009120839p:plain

Googleの検索に引っかからずほぼ諦めていたが、登録しておいたサイトマップが9月22に応答した。

ステータスが「成功しました」に変わっていた。

しかし検出されたURL数は0。

ただ、いままで成功しましたのステータスは見たことがなかったので大きな変化だった。

他のサイトマップも検知された2020年10月08日

登録しておいた他のサイトマップも反応を見せた。

f:id:itkotsukotsu:20201009123454p:plain

  • /sitemap.xml ⇒ 「成功しました」 検出されたURL: 9
  • /sitemap_index.xml ⇒「成功しました」 検出されたURL: 9
  • /sitemap_periodical.xml?year=2020&month=8 ⇒「成功しました」 検出されたURL: 4
  • /sitemap_periodical.xml?year=2020&month=9 ⇒ 「成功しました」 検出されたURL: 5
  • /sitemap_common.xml ⇒ 「取得できませんでした」 検出されたURL: 0

正しいとされる sitemap.xmlsitemap_index.xml はともに同件のURL数を検知した。

Googleの検索にも引っかかるようになった。

sitemap_common.xmlはどうも不要なサイトマップみたいだったので削除した。

今後はしばらく様子見

長らくGoogle Search Consoleに登録できなかったはてなブログサイトマップが登録できた。

Googleはてなブログ側の対応かわからないが、長年悩ませてきた問題が解決したことに感謝したい。

引き続き経過を見守ろうかと思います。

f:id:itkotsukotsu:20201009123404p:plain:w300

iptables 考え方、設定方法について(入門)

iptablesとは

iptablesLinuxに搭載されているパケット操作のための仕組み。

よく使う方法としてはパケットフィルタとしての使い方で簡単なファイアウォールを作れたりする。

本質としてはパケット操作全般が可能であるため、しっかり作りこめばルータ機能を実装したり、kubernetesDockerのようなコンテナ内通信を実現できる。

iptablesの基礎

iptablesは古くからLinuxに搭載されているパケット操作ツールである。

iptablesはパケット操作の設定をするためのフロントエンドインタフェースであり、実態としてはLinuxカーネルのNetfilterに対して設定を行う。

LinuxカーネルのNetfilterが実際のパケットを処理するため、ここらの関係性を理解する必要がある。

なお、CentOS7以降ではパケットフィルタツールとしてfirewalldが導入されたが、firewalldがやっているのは実はiptablesを操作するだけのフロントエンドツール。

つまり、FirewalldiptablesNetfilter のように内部では操作が行われている。

やはり最終的なNetfilterの理解は避けられない。

iptablesにおける登場人物

iptablesNetfilterのフロントエンドツールであり、iptablesが構想する概念がある。

大きく分類すると以下がある。

  • テーブル(実行操作)
  • チェイン(実行タイミング)
  • パラメータ(条件)

テーブル

テーブルはiptablesで実現する操作である。

指定可能なテーブルは以下だ。

テーブル 説明
filter パケット通過の認可
nat ネットワークアドレス変換(ポート変換可)
mangle TOS(Type Of Service)フィールドの操作
raw NOTRACKターゲットの操作

filterテーブル

filterテーブルはパケットの通過の許可や拒否を行うことができる。

iptablesでパケットフィルタを実現するにはこのテーブルが使われる。

filterは通過の認可(ACCEPT, DROP)に対して、IPヘッダにおけるIPアドレスやポート番号のsourceとdestinationを指定可能だ。

natテーブル

natテーブルはネットワークアドレス変換を行うことができる。

NATが必要なケースは少ないがグローバルIPとプライベートIPの対応付けやNAPT(IPマスカレード)で使われる。

ルータ機能を持たせる必要がある際に使われることが多い。

mangleテーブル

mangleテーブルは TOS(Type Of Service)フィールドと呼ばれるIPヘッダーに含まれるQoS(Quality of Service)を実現するために使われる

filterやnatと比べ使用されるケースは少ないが、IPPBX等でパケットの優先付けや帯域制御を行う場合に使われる。

TOSの書き換えとなるとハードウェアルータ等では対応していないことが多く、ソフトウェア処理だからこそできることでもある。

rawテーブル

rawテーブルはNOTRACKターゲットと呼ばれるIPヘッダーに含まれる追跡マークを除外することができる。

大量のパケットが流入する環境において、追跡マークを除外することで特定の危機への負荷を軽減することが可能だ。

高負荷が想定される環境でiptablesを用いてソフトウェア処理をさせるケースが考えづらいため、ほぼ使われないだろう。

チェイン

チェインはパケット操作を実行する場所(タイミング)を定義する。

f:id:itkotsukotsu:20201009005539p:plain

種類 説明
PREROUTING 入力(受信時)
INPUT 入力(自ホスト向け受信)
FORWARD 転送(ルーティング)
OUTPUT 出力(時ホストから送信時)
POSTROUTING 出力(送信時)

チェインは上記の5つあり、目的に合わせて選択する。

自ホスト向けのファイアウォールとしてパケットフィルタしたいならINPUTをチェインとすればいいだろう。

Linuxルータとしてアドレス変換(NATやNAPT)を実現するなら、出力するパケットのアドレスを変えるためにPOSTROUTING時にマスカレード処理を書く。

なお、チェインには適用可能なテーブルが定まっている。

テーブル 利用可能なチェイン
filter INTPU, OUTPUT, FORWARD
nat OUTPUT, PREROUTING, POSTROUTING
mangle INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING
Raw OUTPUT, PREROUTING

パラメータ(オプション)

パラメータは指定したチェインとテーブルに対して、細かい条件をしてすることができる。

パケットフィルタであれば、送信元IPや宛先IPを指定して認可を設定できる。

アドレス変換も対象とするネットワークアドレス帯を指定することが可能だ。

NICを複数もつホストであればインタフェースを指定してNIC毎に設定も可能

パラメータ 内容
-p (--protocol) プロトコルの指定(icmp, tcp, udp, or all)
-s (--source) 送信元IPアドレス(ネットワークアドレスも可)
-d (--destination) 送信先IPアドレス(ネットワークアドレスも可)
--sport 送信元ポート番号
--dport 宛先ポート番号
-i (--in-interface) 入力元インタフェース
-o (--out-interface) 出力先インタフェース
-j (--jump) ターゲットを指定(ACCEPT, DROP, REJECT, REDIRECT, LOG)

あとはtcp-flagsとしてSYNやACK等も指定可能。細かいところは公式ドキュメントを参照されたい。

iptables-extensions

iptablesの書き方

iptablesは複数のエントリが記述可能なため、エントリ間の効果の範囲と優先度を意識する必要がある。

エントリの優先順位

iptablesのエントリは上部から順番に適用される。

Chain INPUT (policy ACCEPT)
target     prot opt source               destination   
ACCEPT     all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

上記はCentOS7の例だが、INTPUのチェインにおいてAcceptのエントリがある。

このあとにDROPREJECTが記述されており、これはホワイトリスト形式での記述になる。

もちろんDROPを優先度を上げて、具体的に許可するエントリを書くブラックリスト方式も可能だ。

エントリの操作として--replace--insertがあり、任意の場所で修正変更操作が可能だ。

まとめ

今回はiptablesの設計思想と記述方法について記載した。

iptablesの各エントリの意味とエントリの適用順序を理解することでパケットの処理を理解することが可能だ。

最近だとDockerやKubernetes等の仮想ネットワークはiptablesで実現されており、 ネットワーク障害時の切り分けそしてiptablesを読みれると良いだろう。

CentOS8のMinimalインストール と 使用方法(dnf, nftables)

CentOS8のインストール方法

RHEL(Red Hat Enterprise Linux)系統のOSとしてCentOSがあるが、長らくCentOS7を使っていた。 2019年にCentOS8がリリースされ、徐々に業界でもRHEL8やCentOS8の採用が始まってきているようなので、導入してみた。

構築環境

  • ホスト: Macbook12インチ(Windows10 BootCamp)
  • 仮想化ソフト: VirtualBox6.1.2

CentOS8のイメージ(ISO)をダウンロード

f:id:itkotsukotsu:20200925210509p:plain

CentOS8は公式HPからダウンロードできる。

Download

日本サーバでも色々用意されているので好みのところからダウンロード。

理研とかで良ければ以下がリンク。 ftp.riken.jp

CentOS8(RHEL8)からMinimal ISOが無くなった?いや復活したみたい。

f:id:itkotsukotsu:20200925210720p:plain

CentOS7を利用していた時は不要なデータもダウンロードしたくないし、インストールもしたくないので、Minimalバージョンを好んで使っていた。

このMinimalはOSを稼働させる最小限のOSSパッケージのみで構成される。

RHEL8ではこのMinimalのISOの配布が無くなったらしい。

RHLE8と同列のOracleLinux8もMinimal版の配布はされていなかった。

CentOS8もMinimalが無くなったと聞いていたような気がしたが、普通にあったのでこれをダウンロードする。

http://ftp.tsukuba.wide.ad.jp/Linux/centos/8.2.2004/isos/x86_64/CentOS-8.2.2004-x86_64-minimal.iso

CentOS8をVirtualBoxにインストール

f:id:itkotsukotsu:20200925211601p:plain

VirtualBoxでCentOS8をインストールする。

OSバージョンはRed Hat (64-bit)で、あとは好きなように。

インストーラが立ち上がったら、一通り設定を行う。

といってもMiminalの場合は2か所のみでそれとrootパスワードくらい。

  • SYSTEM: Installation Destination
    すでにディスクにチェックが入っているので、Doneを押す
  • SYSTEM: Network & Host Name
    初期値はNICが有効になっていないので、ここで有効(DHCP)にしておいたほうがいいだろう。

インストール完了後はコンソール画面で操作するのが辛いので、SSH接続する。

VirtualBoxのNATポートフォワード機能を使ってVMに簡単にSSHする

f:id:itkotsukotsu:20200925212209p:plain VirtualBoxVMはホストのWindowsを経由してインターネット接続できるようにNATになっている。

正確にはIPマスカレードによるポート変換を行っている。

VirtualBoxの仮想LANを経由してゲストOSにアクセスすることもできるが、このNATが邪魔してWindowsホストから直に通信ができない。

NAT自体は必要な機能なので、代わりにVMの設定からポートフォワード設定をすることで、WindowsホストのポートとゲストOSのポートをバインドすることで接続性を確保する。

このポートフォワード機能はとても便利だ。なぜHyper-Vにはないのだろうか。

CentOS8の使い方

yumがdnfになった

CentOS8(RHEL8)からパッケージ管理ソフトがyumからdnfとなった。

yumが裏ではPython2系で動作しているのに対し、dnfはPython3系で動作する。

Python2は将来的にも衰退方向にあるため、ここで切り替える判断をしたようだ。

といってもyumとdnfはコマンドの文法に高い互換性がある。

実際yumコマンドは動作するが、実態としてはdnfのバイナリ実行ファイルにシンボリックリンクが張られているだけ。

[root@localhost ~]# ls -l /usr/bin/yum
lrwxrwxrwx. 1 root root 5 Apr 24 15:57 /usr/bin/yum -> dnf-3

なので、dnfを意識しなくてもyumと入力するだけで、dnfを使っていることになる。

しかしdnfに入れ替わったのだからyumと入力するのは卒業したほうがいいだろう。

パケット処理機能のiptablesがnftablesに

iptablesがnftablesに変わったのも大きな変化だ。

今までiptablesでパケット操作を行っていたが、これがnftablesとなった。

nftablesは今までバラバラだったiptablesやその他のネットワーク関連コマンドを共通のコマンド文法で操作できるもの。

ただ、nftablesでもiptablesでも結局はLinuxKernelのNetfilter経由で操作することには変わりない。

iptablesコマンドも実行はできるが、dnf同様にnftablesとして実際は動作している。

[root@localhost ~]# iptables -V
iptables v1.8.4 (nf_tables)

まとめ

  • CentOS8 でもMinimal ISOはある
  • yumがdnfになった
  • iptablesがnftablesになった

そのほかCentOS7のyumリポジトリ上のOSSがいろいろバージョンアップしているようだ。

気になるのはCetnOS8の公式リポジトリDockerがないこと。

Docker公式にもDocker_CEではCentOS8はサポートしていないって書いてあるし。

Qiitaに無理やりCentOS7と同じ方法でCentOS7にインストールしている例があるけど、iptables経由でNetfilter操作したら整合性取れなくなるから、やめたほうがよさそう。

CentOS8が主流になるまでにはもう少し時間かかりそうかな。

HHKBのラバードームを復活させて軽くする方法

HHKBは経年劣化する

f:id:itkotsukotsu:20200906235054j:plain:w600

HHKBは素晴らしいキーボードだ。

この前HHKB Professional Hybrid Type-Sを入手したが、異様にキーの打鍵感が軽い。

もともと前モデルであるHHKB Professional2 Type-Sを所持しているが、これと比較するとまるで別物。

公式ホームページを見てもキーの重さも45gで仕様の変化はなさそうだ。

打鍵感を比べても新品で軽いHybridのほうが良い。

分解写真を見るとどう見ても新しいHybridモデルも同じラバードームを使っている。

反発力を生み出すカップラバーがゴム製

HHKBの打鍵感はこのラバードームから生み出されているのだ。

HHKB公式サイトの説明

f:id:itkotsukotsu:20200925004819p:plain

公式サイトより引用

このカップラバーがゴムでできているんですよ。

4年たったHHKBはゴムが固くなり、押下圧が55gくらいあるキーボードとなってしまった。

Professional 2も買った当初は軽かった記憶が。。。

固くなったラバードームを柔らかくする

ゴムが劣化して固くなっているので、要はゴムを復活させればよい。

f:id:itkotsukotsu:20200925014558p:plain:w500 https://www.yodobashi.com/product/100000001001990220/

ゴムの復元方法について調べると、上記のラバープロテクトという商品がよさそうだった。

使い方としてはゴムの劣化の保護ではあるのだが、劣化したゴムにも有効ということで、評価が非常に良い。

車向けの製品のようだが、HHKBのラバードームに使っている人なんていなかった。まぁいないだろう。

HHKB Professional 2 を分解

まずはキートップを外す。

ちょっと中身を見せられる状態ではなかったので、掃除してから写真は撮った。

f:id:itkotsukotsu:20200925015008j:plain:w600

f:id:itkotsukotsu:20200925015216j:plain:w600

次に背面を外す。

コントローラ基盤との配線があるので、誤って切らないように気を付ける。

f:id:itkotsukotsu:20200925015255j:plain:w600

お勧めはコントローラ側のネジを外し、配線を取らずにとってしまう方法だ。

わりと配線が強くソケットに止まっているので、壊しそうで怖い。

問題のラバードームが登場

ケースを取り外すと、ラバードームが現れる。

f:id:itkotsukotsu:20200925015407j:plain:w600

基盤とラバードームは軽い接着剤でくっついているようだが、簡単に取れる。位置固定のため程度だろう。

f:id:itkotsukotsu:20200925015444j:plain:w600

早速ラバードームの反発力を見ると固い。

ゴムが柔軟性を失い、固い動きになっている。

ラバープロテクトをかける

早速ラバードームにラバープロテクトをかけました。

f:id:itkotsukotsu:20200925020514j:plain:w600

ゴムを溶かして同化する素材なのが、ラバープロテクトの液がぐんぐんゴムに浸透していきました。

乾くまで時間がかかるが、ラバープロテクトをかけたものを比較すると、全然柔軟性が違う。

弾力はあるし、とても軽い。

一つ試して問題なかったので、全部ラバープロテクトをかけました。

HHKBを元に戻す

分解したのをもとに戻して、HHKBの打鍵感を確かめると、めっちゃめちゃ軽い!

新品のHHKBと比較したらまだ固いが、4年の経年劣化が2年分くらいは戻った感じがした。

押下圧でいうと55h(劣化状態) ⇒ 50 くらいにはなったかな。

まとめ

  • HHKBは経年劣化でラバードームが固くなる
  • ラバープロテクトで柔軟性を取り戻すことができる
  • 交換パーツは今のところ入手しやすいものがない

本当はラバードームの交換品が入手できれば良いだが、量産品がなさそう。

HHKBは使っているうちに劣化するから固くなっていることに気づき辛い。

数年HHKBを使っているのであれば、ぜひラバードームの復活を試してみてほしい。

買った直後のHHKBの軽いタッチに戻せるはずだ。

ThrottleStopでCPUのクロックダウンを防ぐ(サーマルスロットリング無効化)

負荷時にノートPCのCPUクロック数が下がる

ノートPCやタブレット等で高負荷時にCPUが高温になるとCPUの発熱防止機能となるサーマルスロットが機能する。

サーマルスロットリングはCPUのクロックを低下させて、消費電力を抑えて発熱量を低下させるものだ。

一部のPCでは冷却能力が不足し、一定の温度に達するとサーマルスロットが機能し、CPUの処理速度が低下する。

MacbookでCPUクロックの低下の例

f:id:itkotsukotsu:20200922131618p:plain

Macbook12インチでbookCamp経由でWindowsを動作させているが、ファンレスPCのためCPU温度が上がりがちなモデル。

少し作業するだけて、CPU周波数が0.9Ghzで張り付いてしまう。

ただ、不思議なことに本体を触ってもMacOSを稼働させたときのように劇熱ではないのだ。

MacOSのではCPU温度が100℃近く上昇を続け、90℃付近でサーマルスロットが機能して均衡が保たれていた。特に動作の低下も感じづらい。

Windows10では全然熱くないのにすぐクロックダウンしてしまう。0.9Ghzまで低下すると動作速度低下を体感できるレベルで、作業に大きく支障がでる。

クロックダウン時のCPU温度

CPU温度を確認すると50℃しかなかった。

f:id:itkotsukotsu:20200922132229p:plain

CPUの温度計測はHWMonitorから可能だ。

HWMonitor

高負荷時のサーマルスロットリングが発生しているのに50℃というのはおかしい。

クロックダウン後の冷却後にクロックが再上昇していないように見える。

実はこの現象は超小型PCの GPD Pocketでも発生しており、不当にCPUが低周波数でとどまる症状が出ていた。

CPUのサーマルスロットをThrottleStopで停止する

どうもWindows OSは不当にCPUクロックを低下させたままになる症状がありそうだ。

サーマルスロットリングの動作アルゴリズムが不明瞭だが、ハードウェアレベルでのスロットリング動作とOSのソフトウェアレベルでのスロットリング動作がある。

アプリケーションからソフトウェアレベルのサーマルスロットリングを無効化できるソフトを見つけた。

ThrottleStop f:id:itkotsukotsu:20200922133116p:plain

記事を書いたときは9.2がStableバージョン。 CPUの動作を変更させるリスクがあるソフトなので、Stableバージョンをお勧めする。

ThrottleStopでサーマルスロットリングの停止

ThrottleStopをダウンロードし、zipを展開すれば特にインストーラ形式でないため準備完了だ。

f:id:itkotsukotsu:20200922133419p:plain

このソフトはCPUの熱が上昇するため、自己責任で使うよう警告が出る。

ThrottleStop起動後は以下のような画面。

f:id:itkotsukotsu:20200922133604p:plain

Settings内で細かい調整は可能だが、サーマルスロットリングのみ無効化したいなら以下を有効にしてアプリケーション下部のTurn Onを押せば良し。

  • Settings -> Clock Mod
  • Settings -> Set Multiplier
  • Settings -> SpeedStep

ThrottleStop起動前(0.9Ghzで張り付き)

f:id:itkotsukotsu:20200922140436p:plain

CPUが0.9Ghzでとどまり、CPU使用率は99.1%となっていることがわかる。

CPU温度も54℃で低温だ。

ThrottleStop起動後(2.9Ghzまで上昇)

f:id:itkotsukotsu:20200922140613p:plain

ThrottleStopをTurn On後にCPUのクロック数が急上昇し2.9Ghzまで到達した。

これはMacbook搭載のIntel Core m7プロセッサのターボブーストの上限に近い値。

CPU温度も96℃に到達し、サーマルスロットリングの解除に成功したようだ。

ThrottleStop有効時のハードウェアサーマルスロットリングについて

ThrottleStopでサーマルスロットリングを無効化するとCPUの温度上昇が止まらないのではと不安に思うこともあるだろう。 ThrottleStop有効にして、CPUを高負荷にしてみた結果が以下だ。

Intel® Power GadgetでCPU周波数の変化を測定

Intel® Power Gadgetを用いるとCPU温度、周波数の変化をグラフで見ることが可能だ。

Intel® Power Gadget

ThrottleStopを有効にして、CPUに負荷をかけて経過を観察した。

f:id:itkotsukotsu:20200922141458p:plain

上記のグラフのPackage Frq0 がCPUの動作周波数だ。

CPUに負荷をかけた直後に周波数が2.9Ghzまで上昇している。

一定期間2.9Ghzを維持したあとにクロックダウンしており、その後は2.2~2.3Ghzで維持された。

これはハードウェアサーマルスロットリングが動作しているためであり、不当なクロックダウンは起きておらず、CPU温度と動作速度の均衡がとれた値に収束する。

Macbook12インチに限っては均衡値が約2.2Ghzなのだろう。

まとめ

  • WindowsOSではOS側の制御で不当にCPU動作クロックが低下する
  • ThrottleStopを使ってソフトウェアサーマルスロットリングの無効化が可能
  • ハードウェアサーマルスロットリングは独立して動作し、安全な温度で動作

Macbookに限らず、メーカの調整が不十分なWindows端末はCPUクロックが低下する症状が多々見られる。

ThrottleStopを使って正常動作に戻すことは可能だが、温度上昇はPC寿命を短くする可能性もあるため、十分注意して運用してほしい。