ドキュメント

Apache用モジュールをコンパイルできるようにする

  • httpd-devel (apxs) をインストールしておく。
    # yum install httpd-devel

バーチャルホスト設定

設定

  • /etc/httpd/conf.d/VirtualHosts.conf
    # Use name-based virtual hosting.
    NameVirtualHost *:80
    
    <VirtualHost *:80>
    	ServerName	www.takeash.net
    	DocumentRoot	/var/www/html/
    </VirtualHost>
    
    <VirtualHost *:80>
    	ServerName	vh1.takeash.net
    	DocumentRoot	/var/www/vh1-html/
    	<Directory "/var/www/vh1-html">
    #		AllowOverride	All
    	</Directory>
    </VirtualHost>

エラー対策

  • バーチャルホストが表示されない。
    • エラーメッセージ
      [warn] _default_ VirtualHost overlap on port 80, the first has precedence
    • 原因
      NameVirtualHost ディレクティブが設定されていない。
    • 対処
      NameVirtualHost ディレクティブを設定する。
      httpd.conf を修正するより conf.d に VirtualHosts.conf として専用のファイルを作成しておく方が忘れなくていいかも。

Digest 認証

  • 認証、承認、アクセス制御
  • mod_auth_digest
    • レルム/ユーザ/パスワード追加
      htdigest [-c] passwdfile <realm> <username>
    • /etc/httpd/conf.d/DigestAuth.conf
      <Directory "/var/www/html/Download/<realm>">
      	AllowOverride AuthConfig
      	AuthType Digest
      	AuthName "<realm>"
      	AuthUserFile /var/www/passwd/passwords_digest
      	Require user <username>
      	Options None
      	Options Indexes
      	DirectoryIndex index.html index.htm index.php
      	Order allow,deny
      	Allow from all
      </Directory>

mod_ssl

  • インストール
    # yum install mod_ssl

自己署名証明書使用

Certbot 使用

  • Certbot 使用前準備

    • ホスト名が正引きできること。(ワイルドカード不可)
    • バーチャルホストのサーバ名と要求するドメイン名のどれかが一致すること。
    • https でアクセス可能になっていること。
      • https ポート解放
        # firewall-cmd --add-service=https --permanent
  • Certbot インストール (EPEL リポジトリ)

    # yum install python-certbot-apache
  • 証明書取得
    取得に成功すると「/etc/letsencrypt/live/<ドメイン1>/」に証明書が作成される。

    # certbot --apache certonly -m <メールアドレス> -d <ドメイン1> [-d <ドメイン2> ...] --agree-tos
  • /etc/httpd/conf.d/ssl.conf (抜粋)

    Listen 443 https
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/<ドメイン1>/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/<ドメイン1>/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/<ドメイン1>/chain.pem
  • /etc/httpd/conf.d/VirtualHosts.conf (抜粋)
    バーチャルホスト毎に SSL 設定が必要。

    <VirtualHost *:80 *:443>
            ServerName      vh1.<ドメイン1>
            DocumentRoot    /var/www/vh1-html/
            SSLEngine on
            SSLCertificateFile /etc/letsencrypt/live/<ドメイン1>/cert.pem
            SSLCertificateKeyFile /etc/letsencrypt/live/<ドメイン1>/privkey.pem
            SSLCertificateChainFile /etc/letsencrypt/live/<ドメイン1>/chain.pem
            <Directory "/var/www/vh1-html">
                    AllowOverride   All
            </Directory>
    </VirtualHost>
  • 自動更新スクリプト /etc/cron.monthly/certbot.sh

    #!/bin/bash
    /bin/certbot renew
  • Certbot

  • Webサーバー間通信内容暗号化(Apache+mod_SSL+Certbot) - CentOSで自宅サーバー構築

Certbot 使用(ワイルドカード)

  • Certbot インストール (EPEL リポジトリ)

    # yum -y install yum-utils
    # yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
    # yum install certbot-apache
  • 証明書取得(手動)
    途中HTTPへのテキストファイルの配置とDNSへのTXTレコードの追加を指示されるので、追加してからEnterを押して先へ進む。
    取得に成功すると「/etc/letsencrypt/live/<ドメイン>/」に証明書が作成される。

    # certbot certonly --manual --server https://acme-v02.api.letsencrypt.org/directory -d "*.example.com" -d example.com
  • /etc/httpd/conf.d/ssl.conf (抜粋)

    SSLCertificateFile /etc/letsencrypt/live/<ドメイン>/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/<ドメイン>/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/<ドメイン>/chain.pem
  • apache 再起動

    # systemctl restart httpd.service
  • 証明書更新
    「--manual」で取得した場合は「renew」による自動更新ができないので、既存の証明書を削除し同名で取得し直す。

    # certbot delete
  • 証明書の有効期限を表示
    getExpireDate.sh

    #!/bin/bash
    
    CommonName=example.net
    
    NotAfter=`openssl x509 -noout -dates -in /etc/letsencrypt/live/${CommonName}/fullchain.pem | \
      grep notAfter | \
      sed -e "s/notAfter=//" | \
      date -f - --iso-8601`
    echo ${NotAfter}

mod_security

インストール

  • EPELリポジトリ
    # yum install mod_security mod_security_crs

設定

  • /etc/httpd/conf.d/mod_security.conf (抜粋)

    # Maximum request body size we will
    # accept for buffering
    #SecRequestBodyLimit 131072
    SecRequestBodyLimit 5242880
    SecRequestBodyNoFilesLimit 51200
  • /etc/httpd/modsecurity.d/modsecurity_localrules.conf

    # Drop your local rules in here.
    
    # White List IP
    SecRule REMOTE_ADDR "@pmFromFile /etc/httpd/modsecurity.d/whitelist_ip.txt" \
            "phase:1,id:'1000001',nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off"
    
    # White List URI
    SecRule REQUEST_URI "@pmFromFile /etc/httpd/modsecurity.d/whitelist_uri.txt" \
            "phase:1,id:'1000002',nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off"
    
    # White List URI 2
    SecRule REQUEST_URI "@rx ^\/Etc\/" \
            "phase:1,id:'1000003',nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off"
    
     # White List Sub-Domain
     SecRule REQUEST_HEADERS:Host "@pmFromFile /etc/httpd/modsecurity.d/whitelist_subdomain.txt" \
             "phase:1,id:'1000004',nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off"
    
    # ZmEu Attack / phpMyAdmin
    SecRule REQUEST_URI "@rx (?i)\/(php-?My-?Admin[^\/]*|mysqlmanager|myadmin|pma2005|pma\/scripts|w00tw00t[^\/]+)\/" \
            "severity:alert,id:'0000013',deny,log,status:400,msg:'Unacceptable folder.',severity:'2'"
    • mod_security-2.7.1 でエラーが出るから適当にid追加したけど、idの振り方のルールってどこにあるのかな?
      ModSecurity: No action id present within the rule
  • /etc/httpd/modsecurity.d/whitelist_ip.txt
    mod_security による制限を行わない IP アドレスを列挙する。
    コメントは行頭から「#」で始める。

    # localhost
    127.0.0.1
    
    # example.com
    xxx.xxx.xxx.xxx
    
    # example.net
    yyy.yyy.yyy.yyy
  • /etc/httpd/modsecurity.d/whitelist_uri.txt
    mod_security による制限を行わない URI を列挙する。

    /cgi-bin/etc/PrintEnv.cgi
    /cgi-bin/etc/PrintEnv_txt.cgi
    /cgi-bin/etc/index.cgi
    /cgi-bin/etc/testCGI.cgi
  • /etc/httpd/modsecurity.d/whitelist_subdomain.txt
    mod_security による制限を行わないホスト名を列挙する。

    # WebApp1
    vh1.takeash.net
  • /etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_20_protocol_violations.conf

    • id:958291 "Range: 0-", mp4 等のストリーミングや分割ダウンロードが行われるファイルのダウンロードで引っかかる。

リンク

mod_geoip

インストール

  • EPELリポジトリ
    yum install mod_geoip

設定

  • /etc/cron.monthly/updateGeoIP
    データベースの自動更新スクリプト
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
    gunzip GeoIP.dat.gz
    mv -f GeoIP.dat /usr/share/GeoIP/GeoIP.dat
    /sbin/restorecon -v /usr/share/GeoIP/GeoIP.dat
  • GeoIP が表示されない場合は、SELinux のラベルを確認。
    # ls -Z /usr/share/GeoIP/
    Good) unconfined_u:object_r:usr_t:s0
    NG)   unconfined_u:object_r:admin_home_t:s0
    ラベルが正しくない場合は下記コマンドで修正する。
    # sealert -a /var/log/audit/audit.log
    # /sbin/restorecon -v /usr/share/GeoIP/GeoIP.dat
    ラベル修正後、httpd を再起動すること。
    # service httpd restart

リンク

Apacheでhttp-equiv属性値を反映させる

Apache に DoS 攻撃対策 mod_evasive

cgi-bin ディレクトリでファイル名を省略したときに index.cgi を実行する設定

  • httpd.conf に ScriptAliasMatch を追加する。

  • 修正前

    ScriptAlias /cgi-bin/ /var/www/cgi-bin/
  • 修正後

    ScriptAliasMatch ^/cgi-bin/(.*)\.cgi /var/www/cgi-bin/$1.cgi
    ScriptAliasMatch ^/cgi-bin/(.*)/? /var/www/cgi-bin/$1/index.cgi
    ScriptAliasMatch ^/cgi-bin$ /var/www/cgi-bin/index.cgi
    ScriptAlias /cgi-bin/ /var/www/cgi-bin/
  • index.cgi の例

    #!/usr/local/bin/perl
    
    use strict;
    use warnings;
    use utf8;
    use CGI::Pretty;
    
    my $q = new CGI;
    my $host = $q->url(-base => 1);
    print $q->redirect( $host . '/' );
    
    # EOF
  • Apacheで、http://hoge.hoge/cgi-bin/foo/にアクセスできるようにする方法

Apache で外部からの直リンクを禁止する

Basic認証にタイムアウトを設定する