This shows you the differences between two versions of the page.
| Previous revision | |||
| — | fuss:apache [2025/10/21 23:26] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Using Apache Memory Cache ====== | ||
| + | |||
| + | Apache has its own memory cache module '' | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | Cache Enable mem / | ||
| + | MCacheSize 1074741824 | ||
| + | MCacheMaxObjectCount 1000 | ||
| + | MCacheMaxObjectSize 1048576 | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | ====== Usual Required Modules ====== | ||
| + | |||
| + | < | ||
| + | authz_host_module | ||
| + | log_config_module | ||
| + | headers_module | ||
| + | setenvif_module | ||
| + | # Proxy needed by default on OSX | ||
| + | proxy_module | ||
| + | mime_module | ||
| + | # DAV needed by default on OSX | ||
| + | dav_module | ||
| + | dav_fs_module | ||
| + | # Status needed by default on OSX | ||
| + | status_module | ||
| + | negotiation_module | ||
| + | dir_module | ||
| + | userdir_module | ||
| + | dir_module | ||
| + | userdir_module | ||
| + | apple_userdir_module | ||
| + | alias_module | ||
| + | rewrite_module | ||
| + | php5_module | ||
| + | </ | ||
| + | |||
| + | ====== Remove Directory Listing ====== | ||
| + | |||
| + | Find: | ||
| + | <code apache> | ||
| + | Options Indexes FollowSymLinks MultiViews | ||
| + | </ | ||
| + | and remove '' | ||
| + | |||
| + | ====== Allow and Deny Network ====== | ||
| + | |||
| + | Every directory can be protected with '' | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | Order deny,allow | ||
| + | Allow from 192.168.1.0/ | ||
| + | Deny from all | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | The '' | ||
| + | |||
| + | ====== Reverse Proxy with Virtual Host ====== | ||
| + | |||
| + | Apache can be configured as a reverse proxy in order to pass traffic to a backend. For example, the following directives: | ||
| + | <code apache> | ||
| + | < | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | </ | ||
| + | will redirect all traffic for '' | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | is specified, then you can have any number of websites to be proxied to their respective backends. | ||
| + | |||
| + | ====== Block Bad Bots ====== | ||
| + | |||
| + | On Debian-like systems, a global rule can be set to block bad bots. In order to do so create a file: ''/ | ||
| + | |||
| + | You must also enable the '' | ||
| + | <code bash> | ||
| + | a2enmod setenvif | ||
| + | </ | ||
| + | ====== Create WebDAV Share ====== | ||
| + | |||
| + | The following directive will share ''/ | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | DAV On | ||
| + | AuthType Digest | ||
| + | AuthName " | ||
| + | AuthDigestDomain / | ||
| + | AuthDigestProvider file | ||
| + | AuthUserFile / | ||
| + | < | ||
| + | Require valid-user | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | It seems that '' | ||
| + | |||
| + | The authentication mechanism to use for maximum compatibility is '' | ||
| + | |||
| + | <code bash> | ||
| + | htdigest -c / | ||
| + | </ | ||
| + | |||
| + | which will prompt for a password. | ||
| + | |||
| + | If you have been trying for a while to access the '' | ||
| + | <code dos> | ||
| + | net stop WebClient | ||
| + | net start WebClient | ||
| + | </ | ||
| + | |||
| + | in order to restart the web-client thereby resetting '' | ||
| + | |||
| + | |||
| + | ====== Set Expiration for Resources ====== | ||
| + | |||
| + | After enabling '' | ||
| + | <code bash> | ||
| + | a2enmod expires | ||
| + | </ | ||
| + | |||
| + | after which [[apache/ | ||
| + | ====== Apache Logs Statistics Through using The Shell ====== | ||
| + | |||
| + | We use '' | ||
| + | |||
| + | ===== Get Number of Unique Visitors ===== | ||
| + | |||
| + | <code bash> | ||
| + | zcat -f access.log* | awk ' | ||
| + | </ | ||
| + | |||
| + | ===== Get Number of Unique Returning Visitors ===== | ||
| + | |||
| + | <code bash> | ||
| + | zcat -f access.log* | awk ' | ||
| + | </ | ||
| + | |||
| + | ====== Apache Image Hot-Link Protection ====== | ||
| + | |||
| + | The idea of preventing people from hot-linking images on your website is contradictory in itself: if you are serving content, then why prevent people from using the content you provide? You can instead shut your website down and keep the content to yourself. | ||
| + | |||
| + | Nevertheless, | ||
| + | |||
| + | <code apache> | ||
| + | SetEnvIfNoCase Referer " | ||
| + | SetEnvIfNoCase Referer " | ||
| + | SetEnvIfNoCase Referer " | ||
| + | SetEnvIfNoCase Referer " | ||
| + | SetEnvIfNoCase Referer " | ||
| + | < | ||
| + | Order Allow,Deny | ||
| + | Allow from env=locally_linked | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Note that branching on referrers is a very bad idea, given upstream caches that may manipulate headers as well as the possibility to circumvent this protection easily by sending a different referrer (your domain) along with the request. Bad, bad idea. | ||
| + | |||
| + | ====== Permanently Redirecting pages ====== | ||
| + | |||
| + | The best way to permanently redirect surfers to a different website is to '' | ||
| + | |||
| + | Suppose you have a virtual host configuration for the domain '' | ||
| + | <code apache> | ||
| + | < | ||
| + | ServerName | ||
| + | DocumentRoot | ||
| + | < | ||
| + | Order allow,deny | ||
| + | Allow from all | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | and that you want to redirect '' | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | ServerName | ||
| + | RedirectMatch permanent ^/(.*) http:// | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | ====== Migrating Website Domain ====== | ||
| + | |||
| + | In this example, we want to move '' | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | ServerName | ||
| + | ServerAlias | ||
| + | RewriteEngine on | ||
| + | RewriteCond | ||
| + | RewriteRule | ||
| + | RewriteCond | ||
| + | RewriteCond | ||
| + | RewriteRule | ||
| + | RewriteCond | ||
| + | RewriteRule | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | this will match both protocols, HTTP and HTTPs (matching the last '' | ||
| + | |||
| + | ====== Disabling Timeouts for Long-Running Services ====== | ||
| + | |||
| + | When using a web-server for live streams or software repositories (git, svn, etc...) it is sometimes useful to disable timeouts. This can be done in apache using the following directives: | ||
| + | |||
| + | <code apache> | ||
| + | < | ||
| + | RequestReadTimeout header=0 body=0 | ||
| + | </ | ||
| + | LimitRequestBody 0 | ||
| + | |||
| + | </ | ||
| + | |||
| + | ====== Make Apache Case-Insensitive ====== | ||
| + | |||
| + | When migrating documents from case-insensitive filesystems to a server with Apache and a case-sensitive system, some links may appear broken and inaccessible. In order to resolve this, enable the '' | ||
| + | <code bash> | ||
| + | a2enmod speling | ||
| + | </ | ||
| + | |||
| + | and then either in an '' | ||
| + | <code apache> | ||
| + | CheckSpelling on | ||
| + | </ | ||
| + | |||
| + | ====== Configure Zend OpCache ====== | ||
| + | |||
| + | To increase the amount of memory alloted to the Zend OpCache found in newer PHP variants, edit the file ''/ | ||
| + | < | ||
| + | ; configuration for php ZendOpcache module | ||
| + | ; priority=05 | ||
| + | zend_extension=opcache.so | ||
| + | </ | ||
| + | |||
| + | and then after that line add the following options: | ||
| + | |||
| + | < | ||
| + | opcache.memory_consumption=256 | ||
| + | opcache.interned_strings_buffer=8 | ||
| + | opcache.max_accelerated_files=8000 | ||
| + | opcache.revalidate_freq=60 | ||
| + | opcache.fast_shutdown=1 | ||
| + | opcache.enable_cli=1 | ||
| + | </ | ||
| + | |||
| + | ====== Redirect to HTTPs and then Authenticate ====== | ||
| + | |||
| + | Suppose you have a ''/ | ||
| + | |||
| + | In the example below a ''/ | ||
| + | |||
| + | <code apache> | ||
| + | Alias /support / | ||
| + | |||
| + | < | ||
| + | Options FollowSymLinks MultiViews | ||
| + | AllowOverride All | ||
| + | |||
| + | SSLOptions +StrictRequire | ||
| + | SSLRequireSSL | ||
| + | ErrorDocument 403 https:// | ||
| + | |||
| + | AuthType Basic | ||
| + | AuthName " | ||
| + | AuthBasicProvider external | ||
| + | AuthExternal pwauth | ||
| + | GroupExternal unixgroup | ||
| + | Require valid-user | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | |||
| + | The reason for this hack is that authentication takes precedence such that using '' | ||
| + | |||
| + | ====== Enable HSTS ===== | ||
| + | |||
| + | If a website accepts a connection through HTTP and then redirects to HTTPS, there is a small window of opportunity where the client talks to the server without encryption that can be abused with a MITM attack. | ||
| + | |||
| + | First enable the headers module: | ||
| + | <code bash> | ||
| + | a2enmod headers | ||
| + | </ | ||
| + | |||
| + | To enable HSTS, edit the SSL virtual host version of your website and add the following stanza: | ||
| + | < | ||
| + | Header always set Strict-Transport-Security " | ||
| + | </ | ||
| + | |||
| + | this will tell browsers to use the HTTPS version of the website without loading the HTTP version first. | ||
| + | |||
| + | The age in the example is set to one year and the '' | ||
| + | |||
| + | ====== Enforce Strong Cryptography ====== | ||
| + | |||
| + | When using Apache SSL, the following directives should be added in order to use strong cryptography: | ||
| + | < | ||
| + | SSLProtocol all -SSLv2 -SSLv3 | ||
| + | SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305: | ||
| + | SSLHonorCipherOrder on | ||
| + | SSLCompression off | ||
| + | SSLSessionTickets off | ||
| + | </ | ||
| + | |||
| + | the settings will disable SSLv2 and SSLv3 as well as enable most of the elliptic-curve cryptography. | ||
| + | |||
| + | Optionally, given a non self-signed certificate, | ||
| + | < | ||
| + | SSLUseStapling on | ||
| + | SSLStaplingResponderTimeout 5 | ||
| + | SSLStaplingReturnResponderErrors off | ||
| + | SSLStaplingCache shmcb:/ | ||
| + | </ | ||
| + | |||
| + | ====== Return 404 for Default Virtual Host ====== | ||
| + | |||
| + | Create a virtual host file or create a virtual host using the following configuration: | ||
| + | <code apache> | ||
| + | < | ||
| + | Redirect 404 / | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | The effect is that if a visitor attempts to access the server IP directly, the default virtual host will return a 404 error. | ||
| + | |||
| + | ====== Calculate the Optimal Maximum Number of Concurrent Connections ====== | ||
| + | |||
| + | To calculate the '' | ||
| + | <code bash> | ||
| + | ps -ylC apache2 --sort:rss | ||
| + | </ | ||
| + | |||
| + | otherwise, the '' | ||
| + | |||
| + | The formula to calculate the value that should be passed to '' | ||
| + | \begin{eqnarray*} | ||
| + | \text{MaxClients} &=& \frac{(\text{Total Memory}\mbox{ }GB) * 1024 - \text{Memory for Other Processes}\mbox{ }MB}{\text{Resident Set Size (RSS)}\mbox{ }MB} \\ | ||
| + | \end{eqnarray*} | ||
| + | |||
| + | For instance, assuming a server with a total of 8GB of RAM, leaving 1GB over to other processes, and with an Apache RSS of 100MB the calculation would become: | ||
| + | \begin{eqnarray*} | ||
| + | \text{MaxClients} &=& \frac{8GB * 1024 - 1024}{100MB} \\ | ||
| + | & | ||
| + | \end{eqnarray*} | ||
| + | |||
| + | ====== Implementing a Global and Consistent Directory Index Style ====== | ||
| + | |||
| + | The following setup implements a global and consistent directory index style that can be used for multiple virtual hosts just by adding an include to any '' | ||
| + | |||
| + | < | ||
| + | + / | ||
| + | | | ||
| + | +---+ / | ||
| + | | + | ||
| + | | | | ||
| + | | +---+ conf-available/ | ||
| + | | | ||
| + | | | ||
| + | | | ||
| + | | | ||
| + | | +---+ includes/ | ||
| + | | | ||
| + | | | ||
| + | | | ||
| + | | | | ||
| + | | +---+ sites-available/ | ||
| + | | + | ||
| + | | | | ||
| + | | +---+ vhost.conf | ||
| + | | | ||
| + | +---+ /var/www/ | ||
| + | + | ||
| + | | | ||
| + | +---+ .fancyindex.css | ||
| + | </ | ||
| + | |||
| + | where: | ||
| + | * ''/ | ||
| + | < | ||
| + | Alias "/ | ||
| + | </ | ||
| + | * ''/ | ||
| + | < | ||
| + | IndexOptions +Charset=UTF-8 | ||
| + | IndexOptions +TrackModified | ||
| + | IndexOptions +Charset=UTF-8 | ||
| + | IndexOptions +FoldersFirst | ||
| + | IndexOptions +NameWidth=* | ||
| + | IndexOptions +FancyIndexing | ||
| + | IndexOptions +HTMLTable | ||
| + | IndexOptions +SuppressDescription | ||
| + | IndexIgnore favicon.ico | ||
| + | IndexIgnore auth* | ||
| + | IndexIgnore include* | ||
| + | IndexIgnore css* | ||
| + | IndexIgnore share* | ||
| + | IndexIgnore upload* | ||
| + | IndexIgnore incoming* | ||
| + | IndexStyleSheet "/ | ||
| + | Options +Indexes | ||
| + | </ | ||
| + | * ''/ | ||
| + | < | ||
| + | < | ||
| + | include " | ||
| + | </ | ||
| + | </ | ||
| + | * ''/ | ||
| + | < | ||
| + | * { | ||
| + | font-family: | ||
| + | } | ||
| + | </ | ||
| + | and is responsible for setting the CSS for the rendered index page. | ||
| + | |||
| + | <WRAP info> | ||
| + | '' | ||
| + | </ | ||
| + | |||
| + | Perhaps a good reason for preferring this setup to using '' | ||
| + | |||
| + | ====== Globally Enable brotli Compression ====== | ||
| + | |||
| + | On Debian, to enable brotli compression, | ||
| + | <code bash> | ||
| + | apt-get install brotli | ||
| + | </ | ||
| + | |||
| + | and then the Apache module must be enabled by issuing the command: | ||
| + | <code bash> | ||
| + | a2enmod brotli | ||
| + | </ | ||
| + | |||
| + | Lastly, create the file ''/ | ||
| + | < | ||
| + | < | ||
| + | AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | The purpose of this file is to instruct the brotli Apache module to compress certain resources, namely textual content as well as javascript with the brotli compressor. | ||
| + | |||
| + | Finally, enable the configuration file by issuing the command: | ||
| + | <code bash> | ||
| + | a2enconf brotli | ||
| + | </ | ||
| + | |||
| + | and reload the Apache configuration: | ||
| + | <code bash> | ||
| + | systemctl apache2 reload | ||
| + | </ | ||
| + | |||
| + | The brotli compressor should now be enabled and will globally compress content as it is transferred from the Apache server. | ||
| + | |||
| + | Note that an alternative configuration is to add the contents of the file ''/ | ||
| + | |||
| + | ====== Rate Limiting an IP Network with mod_QoS ====== | ||
| + | |||
| + | The process of rate-limiting an IP network with Apache mod_qos involves matching an IP address block using the Apache2 '' | ||
| + | < | ||
| + | SetEnvIfExpr "-R ' | ||
| + | </ | ||
| + | where: | ||
| + | * ''" | ||
| + | * '' | ||
| + | |||
| + | followed by using '' | ||
| + | < | ||
| + | QS_EventLimitCount Amazon 10 60 | ||
| + | </ | ||
| + | where: | ||
| + | * '' | ||
| + | |||
| + | ====== Creating Ban Lists for Apache ====== | ||
| + | |||
| + | People conventionally block IP addresses on the networking layer instead of the application layer with Apache and for good reasons due to IP being a property of networking and not something that would be specific to Apache. However, given cloud services Apache might end up downstream with a real IP address passed via an HTTP header such that the banning is only possible after the HTTP session is decapsulated by a reverse proxy or an HTTP server like Apache. | ||
| + | |||
| + | In any case, it makes somewhat sense to block IP addresses at he application layer in that context. Previously we have written scripts that would pull databases, such as [[/ | ||
| + | |||
| + | <code bash> | ||
| + | # | ||
| + | ########################################################################### | ||
| + | ## Copyright (C) Wizardry and Steamworks 2025 - License: GNU GPLv3 ## | ||
| + | ########################################################################### | ||
| + | # This script is used to generate an universal blocklsit for Apache in # | ||
| + | # order to block various IP addresses or networks in CIDR notation by # | ||
| + | # pulling lists from various sources on the Internet. | ||
| + | ########################################################################### | ||
| + | |||
| + | APACHE_CONFIGURATION_FILE=/ | ||
| + | |||
| + | PEERBLOCK=$(curl -s -L " | ||
| + | gunzip | \ | ||
| + | cut -d: -f2 | \ | ||
| + | grep -E " | ||
| + | awk ' | ||
| + | xargs ipcalc -rn | grep -v deaggregate) | ||
| + | |||
| + | AWS=$(curl -s https:// | ||
| + | jq ' | ||
| + | grep -P -o ' | ||
| + | |||
| + | # preamble | ||
| + | cat >" | ||
| + | < | ||
| + | # Amazon AWS Blocking | ||
| + | < | ||
| + | Require all granted | ||
| + | EOF | ||
| + | |||
| + | # body | ||
| + | printf " | ||
| + | while IFS=$' | ||
| + | printf " | ||
| + | done <<< | ||
| + | printf " | ||
| + | while IFS=$' | ||
| + | printf " | ||
| + | done <<< | ||
| + | |||
| + | # postamble | ||
| + | cat >>" | ||
| + | </ | ||
| + | </ | ||
| + | EOF | ||
| + | |||
| + | </ | ||
| + | |||
| + | The script above is a variant of the ipset-generating scripts that is meant to create a single file that is placed within the '' | ||
| + | |||
| + | On the other hand, the script itself is placed within the daily crontab in order to regenerate the lists on a daily basis. | ||
| + | |||
| + | For the curious, the script above blocks Amazon AWS, because it has become very cheap hosting for harvesters and various other indexers (more than likely feeding " | ||
| + | |||
| + | ====== Max Open Files ====== | ||
| + | |||
| + | One error that might appear out of the blue when dealing with Apache is the "max open files" error, perhaps followed by an Apache error '' | ||
| + | |||
| + | Furthermore, | ||
| + | |||
| + | The issue stems from ''/ | ||
| + | <code bash> | ||
| + | ULIMIT_MAX_FILES=" | ||
| + | if [ " | ||
| + | if ! $ULIMIT_MAX_FILES ; then | ||
| + | |||
| + | </ | ||
| + | |||
| + | These lines make it such that the command defined by the variable '' | ||
| + | |||
| + | The issue is mostly encountered under containerization, | ||
| + | <code bash> | ||
| + | APACHE_ULIMIT_MAX_FILES=' | ||
| + | </ | ||
| + | or set a limit, as in: | ||
| + | <code bash> | ||
| + | APACHE_ULIMIT_MAX_FILES=' | ||
| + | </ | ||
| + | |||
| + | Note that the variable '' | ||
| + | |||
For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.