This shows you the differences between two versions of the page.
Previous revision | |||
— | fuss:apache [2025/05/22 15:11] (current) – [Creating Ban Lists for Apache] office | ||
---|---|---|---|
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 mod_qos to rate-limit: | ||
+ | < | ||
+ | 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.