[linux: Apache] Apache basic knowledge ( httpd.conf / .htaccess ) note. #linux #apache
正式名称は Apache HTTP Server でデーモンは httpd
。世界中でもっとも多く使われている OSS な Web サーバソフトウェア。コンピュータに Apache を入れると、そのコンピュータは Web サーバとしての仕事ができるようになる。稼働シェアの高いバージョンは 2.2 と 2.4 でデーモン名や設定ファイルの記述方法が異なる。「 LAMP 環境」の A は Apache の A 。
$ cd /etc/yum.repos.d
$ sudo wget https://repos.fedorapeople.org/repos/jkaluza/httpd24/epel-httpd24.repo
$ cd ~
$ sudo yum --enablerepo=epel-httpd24 install -y httpd24
$ chkconfig httpd24-httpd on
$ service httpd24-httpd start
$ sudo yum intall -y httpd
$ sudo service httpd start
$ sudo chkconfig httpd on
# 設定ファイル
$ vi /etc/httpd/conf/httpd.conf # CentOS など RedHat 系
$ vi /etc/apache2/sites-available/default.conf # MacOS や Debian 系
# ログファイル
$ less /var/log/httpd/error_log
Apache のバージョンや OS の情報を出力しないようにする
HTTPの応答ヘッダーに含まれるPHPバージョンを隠す方法
$ sudo sed -i -e "s/ServerSignature On/ServerSignature Off/g" /etc/httpd/conf/httpd.conf
$ sudo sed -i -e "s/ServerTokens OS/ServerTokens Prod/g" /etc/httpd/conf/httpd.conf
# PHP をインストールしていれば以下で PHP のバージョン秘匿もしとく
$ sudo sed -i -e "s/expose_php = On/expose_php = Off/g" /etc/php.ini
$ service httpd restart
# OS => Apache への実行時定義ファイル追記による環境変数セット
# httpd.conf などで ${DOMAIN} のように取得可能
#
$ echo "export DOMAIN='www.example.com'" >> /etc/sysconfig/httpd # RedHat 系
$ echo "export DOMAIN='www.example.com'" >> /etc/apache2/envvars # Debian 系
# Apache => CGI への SetEnv ディレクティブによる環境変数セット
# PHP の getenv() などで取得可能
#
$ sudo sed -i '$a\SetEnv DEV_MODE 1' /etc/httpd/conf/httpd.conf
WordPress, CakePHP, Laravel など .htaccess
による制御を行っている FW では必須の設定。
# ドキュメントルート変更
DocumentRoot "/var/www/public"
<Directory "/var/www/public">
<Directory "/var/www/public">
# Options Indexes FollowSymLinks
Options FollowSymLinks # ファイル一覧表示の禁止
# Order deny,allow
# Deny from all
AllowOverride All # .htaccess で全設定を上書き可能に
</Directory>
# こっちはキャッシュ無効化
EnableMMAP off
EnableSendfile off
# Apache 2.4 想定
<VirtualHost _default_:443>
SSLEngine on
ServerName localhost:443
SSLCertificateFile "${SRVROOT}/conf/ssl/server.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/ssl/server.key"
# DocumentRoot "${SRVROOT}/htdocs"
CustomLog "${SRVROOT}/logs/ssl_request.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<Directory "${SRVROOT}/htdocs">
Options Includes FollowSymLinks
AllowOverride all
Require all granted
</Directory>
</VirtualHost>
常時 SSL サイトに設定したのち 80 ポートアクセス ( HTTP ) を全て HTTPS へぶんなげ。.htaccess
でディレクトリ単位で指定できるが、通常アプリケーション全体に跨る話であり、かつソースコードで本番環境/試験環境の差分ファイルを運用するの面倒なのでこっちに書く方が楽。
# リライトモジュールを有効化 ( 通常されていると思うが ... )
LoadModule rewrite_module modules/mod_rewrite.so
<VirtualHost *:80>
# Redirect to HTTPS on access by HTTP.
ServerName www.example.com:80
RewriteEngine on
RewriteCond %{HTTP_HOST} (.*)\.example\.com
RewriteRule ^/(.*)$ https://www.example.com/$1 [R=301,L]
</VirtualHost>
LoadModule php7_module modules/libphp7.so
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType application/x-httpd-php .php # add
AddType application/x-httpd-php-source .phps # add
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
# モジュールのコメントアウトを外す
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
# 最終行にでも追加
# / を http://example.com へプロキシ
# フォワードプロキシなら ProxyRequests On にする
#
ProxyRequests Off
ProxyPass / http://example.com/
ProxyPassReverse / http://example.com/
## .htaccess ##
> [Apache チュートリアル: .htaccess ファイル - Apache 2.2](https://httpd.apache.org/docs/2.2/ja/howto/htaccess.html)
- [.htaccess 使い方 RewriteCond 書式 変数名 一覧](https://abhp.net/net/NET_htaccess_850000.html)
- [.htaccessによるURLの書き換え Rewrite(リライト)](https://qwerty.work/blog/2012/02/htaccessurl-rewrite.php)
- [.htaccess でのリダイレクト(転送)設定の書き方](http://www-creators.com/archives/248)
### 画像など特定ディレクトリだけ本番環境を参照させる
- [How to fix Access-Control-Allow-Origin](https://crunchify.com/how-to-fix-access-control-allow-origin-issue-for-your-https-enabled-wordpress-site-and-maxcdn/)
- [Access-Control-Allow-Originヘッダで複数のオリジンドメインを許可する方法](http://blog.applest.net/article/20131219-access-control-allow-origin-multiple/)
- [URLが存在しない場合トップにリダイレクトする.htaccessの設定](https://blog.dksg.jp/2010/06/urlhtaccess.html)
> 以下は WordPress とかでやった例。
```
# public/wp-content/.htaccess
<IfModule mod_headers.c>
SetEnvIf Origin "^https?://(開発者 IP あどれす|すてーじんぐ IP あどれす)$" ORIGIN=$0
Header set Access-Control-Allow-Origin %{ORIGIN}e env=ORIGIN # 全許可なら "*" にまとめても良い
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SERVER_ADDR} [^本番環境 IP あどれす]
RewriteRule uploads/([^除外でぃれくとりあれば].*) https://www.example.com/wp-content/uploads/$1 [R=302,L]
# 上記 www.example.com が本番環境想定
</IfModule>
```
#### リファラによるアクセス制限 ( 直リンク禁止 )
```
# AccessControl referer
SetEnvIf Referer "^http://192\.168\.33\.10\/" chk_url
SetEnvIf Referer "^https://192\.168\.33\.10\/" chk_url
<Files ~ "\.(gif|jpg|jpeg|png)$">
order deny,allow
deny from all
allow from env=chk_url
</Files>
```
#### 当該ディレクトリを制限
```
# 当ディレクトリ配下の拡張子のあるファイルへのアクセスを抑止
<Files ~ "^\.">
deny from all
</Files>
```
#### 静的ファイルのアクセス制限
https://gatespace.jp/2012/06/29/image-403-htaccsess/
```
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?example.com [NC]
RewriteRule .(jpg|jpeg|png|gif)$ - [NC,F,L]
</IfModule>
```
### トークンがないとアクセス不可的な
```
// php などでトークンセットして
if (認証OK) {
setcookie('cookiename', 0cHs2DnN5CLPSNyoEqjD4mmJ0mwnmxsUyI5bkjR8, time()+360000, '/', '.'.DOMAIN, true, false);
}
// .htaccess で制限
SetEnvIf Cookie "cookiename=0cHs2DnN5CLPSNyoEqjD4mmJ0mwnmxsUyI5bkjR8" ok
order deny,allow
deny from all
allow from env=ok
```
### リダイレクト処理
> [.htaccessによるURLの書き換え Rewrite(リライト)](https://qwerty.work/blog/2012/02/htaccessurl-rewrite.php)
#### RewriteRuleのオプション
- [R] 強制的にリダイレクト
- [L] 書き換えが行われたら終了 (Last)
- 現在の書き換え後の URL が後続のルール によってそれ以上書き換えられることを防止
- [F] 強制的にアクセス禁止
- HTTP レスポンス「403 : Forbidden」
- [NC] パターンについて、文字の大小を区別しない(No Case)。
#### 全アクセスを FW のディスパッチャファイル ( index.php ) へ
```
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# リダイレクトの除外対象
RewriteCond %{REQUEST_URI} !(^/exclude_dir/)
# 全部 index.php へ (クエリをurl=へ)
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
```
#### URL の特定文字列を強制的にぶち抜く
```
redirect 301 /en https://www.example.jp
# https://www.example.jp → https://www.example.jp
# https://www.example.jp/hoge → https://www.example.jp/hoge
# https://www.example.jp/en → https://www.example.jp
# https://www.example.jp/en/ → https://www.example.jp
# https://www.example.jp/en/hoge → https://www.example.jp/hoge
```
### HTTPS 強制
```
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
```
### Basic 認証用 .htpasswd 作成
`.htpasswd` の場所はどこでも良いし `.htaccess` 作るのがイヤなら `httpd.conf` の `<Directory>` ディレクションで設定してもよかです。
```sh
$ htpasswd -c -b /var/www/public/.htpasswd ユーザ名 パスワード
$ vim /var/www/public/.htaccess
> AuthUserFile /var/www/public/.htpasswd
> AuthGroupFile /dev/null
> AuthName "表示する文章"
> AuthType Basic
> require valid-user
```
### 文字コード強制
UTF-8 構成のサイトについて、携帯ページだけを Shift_JIS で駆動させたい。
```
AddDefaultCharset shift-jis
AddType "text/html; charset=shift-jis" .html .php
php_value default_charset Shift_JIS
php_value mbstring.language Japanese
php_value mbstring.http_input auto
php_value mbstring.http_output SJIS
php_value mbstring.internal_encoding Shift_JIS
```
### ガラケーアクセスのルーティング
対してURL末尾に `/m/` を付与してリダイレクト
```
<IfModule mod_rewrite.c>
# FEATURE PHONE
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^(DoCoMo|KDDI|DDIPOKET|UP\.Browser|J-PHONE|Vodafone|SoftBank)
RewriteRule ^$ /m/ [R,L]
</IfModule>
```
### www ありへ統一
```
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.jp
RewriteRule ^(.*)$ https://www.example.jp/$1 [R=301,L]
</IfModule>
```