Arch Linuxでポートを開放する.
sshdはsystemctl start sshd
するだけでうまく行くのに,自分でウェブサーバを起動して外部からアクセスしようとしてもウンともスンとも言わないので戦った記録.
Arch Linuxで自作のサーバを建てたいんだけどポート開放がうまく行かない人向け.
結論
0.0.0.0を使ったら一瞬だった.0.0.0.0と127.0.0.1の違いを理解していなかった自分がアホだった.
恥ずかしいからこの記事も消したいけど一応ハマっている人がいるかもしれないから残す.かと言って127.0.0.1でハマる人なんかがサーバを立てるとも思えないので,この記事があっても生き恥をさらすだけで意味ないのかもしれない.
戦いの記録
Arch Linuxでは一般的な推奨事項に
ファイアウォールの設定
ファイアウォールは Linux のネットワークスタックの上部で拡張保護レイヤーとして働きます。Linux カーネルには Netfilter プロジェクトのひとつで、ステートフルファイアウォールである iptables があります。利用するにはフロントエンドを使うか、直接設定します。Arch では全てのポートが閉じられており、ネットワークデーモンは設定をしないかぎり自動で起動しないため、保護すべきサービスがない限りファイアウォールはあまり意味がありません。
とあるので,iptablesを起動して全部ACCEPTにしたりしてもポートがオープンになりませんし,そもそもArchはデフォルトでiptablesを起動しないとiptablesに書いてあります.
これに気づくまでにだいぶ時間がかかりましたが気づいてからは早かったです.
まず,
ネットワークデーモンは設定をしないかぎり自動で起動しないため、
とありますが,対偶を取ると,「自動で起動しているネットワークデーモンは設定をしている」ということになります.
よって,冒頭で記述したsshdはパッケージに設定ファイルが入っているので,何もしなくても22番ポートが開放されネットワークデーモンが起動しています.
そこで,/usr/lib/systemd/system/sshdを調べると,sshd.serviceとsshd.socketという怪しげなファイルが見つかります.
中を見ると
[Unit]
Description=OpenSSH Daemon
Wants=sshdgenkeys.service
After=sshdgenkeys.service
After=network.target
[Service]
ExecStart=/usr/bin/sshd -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always
[Install]
WantedBy=multi-user.target
# This service file runs an SSH daemon that forks for each incoming connection.
# If you prefer to spawn on-demand daemons, use sshd.socket and sshd@.service.
[Unit]
Conflicts=sshd.service
Wants=sshdgenkeys.service
[Socket]
ListenStream=22
Accept=yes
[Install]
WantedBy=sockets.target
と書かれています.
しかし,ここで私は疑問が出てきました.自分のsshdではポートを22番から変えているのです.
試しにsystemctl status sshd.socket
してみるとinactive,つまり起動していません.このため22番ポートという設定が無視されてポート開放できているのです.
(余談ですが,この話もSecure_Shellに書いてあります)
つまり,なんかうまいこと.socket ファイルや.serviceファイルを作ってポートを開放させてあげれば自作サーバをArch Linux上で動かせるはずです.
いろいろググるとこんなページがヒットしまして,あと,Systemdのページをちょろちょろ参考にすれば,
[Unit]
Description=Simple HTTP Proxy
[Service]
ExecStart=/usr/lib/systemd/systemd-socket-proxyd localhost:接続したいポート
PrivateTmp=yes
[Unit]
Description=Simple HTTP Proxy Socket
[Socket]
ListenStream=接続を受け付けるポート
systemctl start service-name.socket
を書くだけです.
詳しくはman systemd-socket-proxyd
例えば,httpサーバを8080番で受け付けて,外部から80番ポートにアクセスしてコンテンツを取得したい場合,接続したいポートに8080,受け付けるポートに80を書けば良い.
この方法が正しいかは知らないので,もしシステムをぶっ壊しても自己責任でお願いします.
書いてsystemd daemon-reload
してsystemd service.socket
とかすると普通に動いて今までのiptables諸々の苦労は何だったんだ…って感じになった.
ちなみに,sshd.socketが起動していないのになんで正しいポートを開放できてるのかは謎です.これがわかったらもっと簡単になるかもしれません.
わかったので更新しました.