|
~ To be, or not to be, or to ask someone to be. ~ null-i.net |
| Linux/CentOS Stream8でサーバ構築/Webサーバ編 | |
|
Webサーバ関連(2022-03-11) 前回の メール編 に引き続き、CentOS Stream8での作業となります。*1 wgetコマンドのインストール†指定したURLからコンテンツをゲットするためのコマンドです。 $ dnf install wget Webサーバにアクセスできるかを確認したり、どこかからファイルをダウンロードする時などに使えます。 Apache httpd のインストール†言わずと知れたWebサーバの老舗。 $ dnf install httpd それから/etc/httpd配下にあるconfigを設定します。 conf/httpd.conf Listen 80 # 動作確認用に、とりあえず起動
# Listen 127.0.0.1:8080 # 後述のプロキシ(squid)起動後はこちら
...(中略)...
ServerName サーバ名
# ここに限らず全体的に「cgi-bin」は狙われやすいので
# 自分の使うWikiやCGIツール上の制約がなければ
# 「mv cgi-bin cgi-bon」とかで置き換えてしまった方が無難だと思う
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
...(中略)...
<IfModule mime_module>
...(中略)...
AddHandler cgi-script .php # うちのサイトではCGIとしてphpを使っています
# 他に必要なCGI関連の設定は以下を参照
# https://httpd.apache.org/docs/2.2/ja/howto/cgi.html
...
</IfModule>
...
# 以下を追記、ゆるいセキュリティ対応
LimitRequestBody 102400 # 初期値は無制限、これは100Kまでに制限する例
LimitRequestFields 50 # 初期値は100、もっとずっと減らして良い
ServerTokens Prod # 初期値はFull、応答ヘッダの情報は最小限にしたい。
TraceEnable Off # 初期値はOn、TRACEメソッドを許可する理由は特に無いので。
# あと、うちの環境だとプロキシ(squid)を使うので
# LogFormat "%{%y%m%d/%H:%M:%S}t %{X-Forwarded-For}i ...
# のように転送前の情報が分かるように、ログにX-Forwarded-Forを追加しています
conf.modules.d/00-mpm.conf LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # この行を有効にする # LoadModule mpm_event_module modules/mod_mpm_event.so # こっちはコメントアウト PHPはスレッドセーフではありません、そしてパッケージからいれた httpdの初期値はスレッド起動(MPM)でした。 Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP. Webサーバで大量のアクセスをさばく場合はプロセス(prefork)ではなくスレッド(mpm)にするべきでしょうけれど、そこまでする必要は無いので素直にprefork起動に変えました。 あと、この時点ではhttpsに未対応です。うちの環境ではSSL/TLS接続はリバースプロキシ(squid)側で受けつけます。 $ firewall-cmd --add-service=http --zone=public --permanent $ firewall-cmd --add-service=https --zone=public --permanent $ firewall-cmd --reload $ firewall-cmd --list-all
$ systemctl enable httpd $ systemctl start httpd 最近のブラウザだとデフォルトでhttps(=443)に繋ぎそうなので、http(=80)の方になるように気をつけつつ動作確認します。 余談:phpでどれをインストールするか†WebサイトでCGIを使う場合は php も入れることが多いと思います。 $ dnf info php Name : php Version : 7.2.24 ところが、Remiを指定して探すと $ dnf --enablerepo=remi-safe search php (以下、抜粋) php.x86_64 : PHP scripting language for creating dynamic web sites php72.x86_64 : Package that installs PHP 7.2 php73.x86_64 : Package that installs PHP 7.3 php74.x86_64 : Package that installs PHP 7.4 (以下、省略) のような感じで新しいバージョンがいっぱい出て来るので、場合によっては 余談:Digest認証を使う例†こんな風に httpd.confを設定することで、アクセス時にパスワード認証を要求できます。 <Directory "指定ディレクトリ">
AuthType Digest
AuthName "realm_name"
AuthUserFile /etc/httpd/htdigestファイルを置いたPATH
Require user user_name
</Directory>
$ htdigest [-c] htdigest realm_name user_name (-c を指定すると新規作成になります) 作成された htdigest ファイルを上記AuthUserFileで指定したPATHに置く なんでこれをメモしたかといえば、 余談:Listen loccalhost:8080 とした場合に失敗する件†squidを起動した後に httpd.conf で Listen hocalhost:8080 した場合、httpdの起動に失敗しました。 Address already in use: AH00072: make_sock: could not bind to address 127.0.0.1:8080 これはどうやら /etc/hosts で localhostとしてIPv4(127.0.0.1)とIPv6(::1)の二つあるときに、両方で bindを試みて失敗するようです。 squid のインストール†リバースプロキシとして使うためにインストールします。 Webブラウサ <--> squid <--> apache-httpd というように通信の仲介をするのが プロキシ(リバースプロキシ)のお仕事です
$ dnf install squid それから squid.confを設定します。 # http_access deny all # 前半のこれはコメントアウト。
# 自分でルールを追記した後にあらためてこれを書きます
# 以下、https://wiki.squid-cache.org/ConfigExamples/Reverse/BasicAccelerator あたりを参考に
http_port 80 accel defaultsite=localhost
https_port 443 accel tls-cert=証明書 tls-key=秘密鍵 defaultsite=localhost protocol=HTTPS
# letsencrypt の場合はそれぞれ
# cert=/etc/letsencrypt/live/ドメイン名/fullchain.pem
# tls-key=/etc/letsencrypt/live/ドメイン名/privkey.pem
cache deny all # キャッシュはしないで毎回Webサーバへ取りにいく
httpd_suppress_version_string on # エラーページでsquidの情報を隠す
# なお、error_directory で自前のエラーページを作成した方がもっと情報を隠せます
# ログ書式は特に時刻がデフォルトだと秒なので、変える事を推奨
# logformat httplog 任意のフォーマット # ログ書式
# (フォーマット例:%tl %>a [%>Hs] %Ss %>st %<st [%>rm %>ru ] [%{User-Agent}>h] [%{Referer}>h])
# access_log daemon:ログのPATH httplog # 書式と保存場所を指定
# logfile_rotate 30 # ログのローテーション日数
# ---このlogfile_rotateを踏まえて、cronとかでローテーションをかける---
# 例: 0 0 * * * /usr/sbin/squid -k rotate
#-----------------------
## 今回 squidを使っている理由と言っても過言では無い部分
## 指定した正規表現にかかったアクセスはTCPリセットで強制断する
# acl bad_url urlpath_regex URL指定の正規表現
# http_access deny bad_url
# deny_info TCP_RESET bad_url
#
## 逆にホワイトリスト方式で絞る案。こっちで書いた方が楽かも?
# acl good_url urlpath_regex URL指定の正規表現
# http_access deny !good_url
#-----------------------
# 自分のサイトのドメイン名へのアクセスのみを許可する
# 不正アクセスで片っ端から漁るときは「IPアドレス直打ち」で来るので、それらを拒絶する
acl web_client dstdomain ドメイン名(うちのサイトの場合はnull-i.net www.null-i.netなど)
http_access allow web_client
# httpd に(localhost:8080 でListenさせて)転送する
cache_peer 127.0.0.1 parent 8080 0 no-digest no-query originserver login=PASS name=my_accel
cache_peer_access my_accel allow web_client
http_access deny all # すべてのルールに漏れたものは最後に deny
# おまじない1。UDPポートでグローバルIPへLISTENされるのを防ぐ。
# 本来は ICPや DNSの連携に使うらしいけど、うちでは使わない想定なので。
udp_incoming_address 127.0.0.1
# おまじない2。以下のようなエラーが出る場合に回避する。
## comm_udp_sendto FD x, (family=2) xx.xx.xx.xx:53: (22) Invalid argument
## idnsSendQuery FD x: sendto: (22) Invalid argument
udp_outgoing_address 自分のIP
以前は cache_peer に no-digest は付けていなかったのですが、ログに「/squid-internal-periodic/store_digest」が頻発するようになってしまったので今回から追加しました。*4 $ systemctl start squid $ systemctl enable squid 特に acl 部分の書き方は慣れだと思います。 余談:URLを日本語に戻す†ブラウザ上でURLへ「index.html?ぬるいねっと」と入力すると、 $ echo %E3%81%AC | perl -MURI::Escape -pe 'print uri_unescape $_'
$ echo %E3%81%AC | perl -e 'while(<STDIN>){ s/%([0-9a-fA-F]{2})/pack("H2",$1)/ge; printf("%s\n", $_); }'
$ echo %25E3%2581%25AC | perl -MURI::Escape -pe 's/%25/%/g; print uri_unescape $_'
$ echo %25E3%2581%25AC | perl -e 'while(<STDIN>){ s/%25/%/g; s/%([0-9a-fA-F]{2})/pack("H2",$1)/ge; printf("%s\n", $_); }'
以上、Webサーバの設定でした。 |
|