Skip to content

Instantly share code, notes, and snippets.

@yano3nora
Last active May 8, 2023 23:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yano3nora/a4ed5e99630a81b83c94c3318aebb076 to your computer and use it in GitHub Desktop.
Save yano3nora/a4ed5e99630a81b83c94c3318aebb076 to your computer and use it in GitHub Desktop.
[dev: Apache] Apache basic knowledge ( httpd.conf / .htaccess ) note. #linux #dev

OVERVIEW

正式名称は Apache HTTP Server でデーモンは httpd 。世界中でもっとも多く使われている OSS な Web サーバソフトウェア。コンピュータに Apache を入れると、そのコンピュータは Web サーバとしての仕事ができるようになる。稼働シェアの高いバージョンは 2.2 と 2.4 でデーモン名や設定ファイルの記述方法が異なる。「 LAMP 環境」の A は Apache の A 。

Refs

Install

2.4 ( httpd24 )

$ 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

2.2 ( httpd )

$ sudo yum intall -y httpd
$ sudo service httpd start
$ sudo chkconfig httpd on

Paths

# 設定ファイル
$ vi /etc/httpd/conf/httpd.conf                 # CentOS など RedHat 系
$ vi /etc/apache2/sites-available/default.conf  # MacOS や Debian 系

# ログファイル
$ less /var/log/httpd/error_log

Tips

サーバ情報の秘匿

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

.htaccess による設定のオーバライド許可

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

SSL/TLS MODULE

# 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>

REWRITE MODULE

VirtualHost で HTTPS へ強制リダイレクト

常時 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>

PHP MODULE

Apache 2.x - php.net

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>

PROXY MODULE

Apache でリバースプロキシ

Apache 2.4 で リバースプロキシの設定

# モジュールのコメントアウトを外す
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

画像など特定ディレクトリだけ本番環境を参照させる

以下は 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(リライト)

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> ディレクションで設定してもよかです。

$ 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment