Installing mod_cloudflare Apache Module To Get Real Visitor IP Addresses

If your Apache server is using CloudFlare for security, or to take advantage of their CDN network, you’ll notice that all client requests now come-in from CloudFlare IP addresses – and the real visitor IP address is hidden.

Not having access to the visitor/client IP address has significant downsides:
You cannot do IP based access controls.
You do not have valid access logs.
You break rewrite rules, .htaccess configurations, and various scripts and web applications.

mod_cloudflare fixes the above issues by providing Apache and PHP with the originating client IP address.

But there is a twist to all this, as you don’t really want to use a 3rd party Apache module (mod_cloudflare) when there is a perfectly good native solution already provided to you by mod_remoteip! And Apache’s mod_remoteip will do the same job as mod_cloudflare, except even better.

mod_remoteip will pull the original client IP address from the CF-Connecting-IP Header provided in each CloudFlare-based request, and use it as-so (after doing some verification).

The full configuration for mod_cloudflare/mod_remoteip is provided by WampDeveloper Pro, and can be loaded into Apache by un-commenting the loading of wampd_cloudflare.conf in httpd.conf.

For everyone else, here is the full CloudFlare configuration for Apache:

# WampDeveloper Pro CloudFlare Integration

# mod_remoteip configuration documentation -
# CloudFlare IP Ranges from -

# To use, just enable your domain name in your CloudFlare account.
# This module and configuration will correctly report the client's true IP / Remote IP (instead of the Proxy IP)
# This fixes issues with web applications, scripts, access and rewrite configurations, and logs

<IfModule !mod_remoteip.c>
	LoadModule remoteip_module modules/

<IfModule mod_remoteip.c>
	# CloudFlare Header
	RemoteIPHeader CF-Connecting-IP
	# Trusted Proxy List
	# note - using RemoteIPTrustedProxy instead of RemoteIPInternalProxy
	# note - RemoteIPTrustedProxy does NOT trust Header provided private intranet addresses (local and LAN addresses)
	# note - RemoteIPInternalProxy is a security risk when using an external Proxy
	# CloudFlare IPv4 Address Ranges
	# CloudFlare IPv6 Address Ranges
	RemoteIPTrustedProxy 2400:cb00::/32
	RemoteIPTrustedProxy 2405:8100::/32
	RemoteIPTrustedProxy 2405:b500::/32
	RemoteIPTrustedProxy 2606:4700::/32
	RemoteIPTrustedProxy 2803:f800::/32

After correcting Apache’s reported client IP and PHP’s reported $_SERVER['REMOTE_ADDR'], this configuration also secures the process by only trusting the Header-provided IP data from CloudFlare servers IP range.

Accessing Remote Databases Using Local PhpMyAdmin

Accessing and managing a remote MySQL database from a “localhost” phpMyAdmin is very simple.


Four things are required –

1. The remote MySQL server must be listening on a publicly accessible IP address (usually my.ini has MySQL configured to listen on – which will not see outside connections).

# The MySQL server
bind-address	=
port		= 3306

Note that some cloud-based VM providers might also require you to connect public:3306 to private:3306 (i.e., “endpoints” on Azure) in their Control Panel.

2. The remote MySQL user-name account has to have its ‘Host:’ field set to either “%” (which means that any IP can connect) or to your public IP address.

Note that this account also has to have at least the minimum set of permissions (‘SELECT‘ vs. ‘ALL‘) granted on the database(s) you need access to…
To create a user:

CREATE USER 'user-name'@'%' IDENTIFIED BY 'user-password';

To grant the user all permission on a specific database-name:

GRANT ALL PRIVILEGES ON `database-name`.* TO 'user-name'@'%';

Or to grant the user all permission on ALL databases:

GRANT ALL PRIVILEGES ON *.* TO 'user-name'@'%';

3. The remote server’s firewall should be configured to allow inbound and outbound port 3306 TCP connections.

4. The local computer needs to have a fully working phpMyAdmin environment installed (such as that provided by WAMP-Developer Pro).

Connecting phpMyAdmin to Remote Server

Edit phpMyAdmin’s configuration file (\WampDeveloper\Tools\phpMyAdmin\, and at the end of it, before the ending ?> line, add in –

/* Remote Server */
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['host'] = '';
$cfg['Servers'][$i]['verbose'] = 'Remote Server Name';
$cfg['Servers'][$i]['user'] = '**********';
$cfg['Servers'][$i]['password'] = '**********'; 
$cfg['Servers'][$i]['hide_db'] = '^(mysql|performance_schema|innodb|information_schema)$';

Update for the host (address of remote server), server name (can be anything – used as display name), and the MySQL’s account user + password info. Do not modify anything else in the file. Save file.

Afterwards –

Access the localhost phpMyAdmin:

Login with user:


Select from the “Current Server” drop-down:

Remote Server Name

phpMyAdmin will do the rest, using the provided info to establish a connection to the remote host/server, and manage the remote database(s) as if they where local.

phpMyAdmin Remote Server

phpMyAdmin Remote Database

Parsing .HTML and .HTM Files as PHP (with htaccess)

To have Apache run .html and .htm files through PHP, add this configuration into the website’s .htaccess file.

AddType text/html .htm .html

# For mod_php5 and mod_php7
<IfModule !fcgid_module>
	AddHandler application/x-httpd-php .htm .html

# For mod_fcgid
<IfModule fcgid_module>
	AddHandler fcgid-script .htm .html
	FcgidWrapper "C:/WampDeveloper/Components/Php/php-cgi.exe" .htm virtual
	FcgidWrapper "C:/WampDeveloper/Components/Php/php-cgi.exe" .html virtual

This will work for both mod_php and mod_fcgid.

Use the correct path in the FCGIWrapper .../php-cgi.exe lines.

WAMP Apache Won’t Start on Windows 10

With everyone taking the Windows 10 upgrade, this question has been coming up often…

I recently upgraded to Windows 10, and as a result WAMPDeveloper’s Apache service won’t start. It produces the following error message:

Error (OS 10013) An attempt was made to access a socket in a way forbidden by its access permissions. :AH00072: make_sock: could not bind to address [::]:80
(OS 10013) An attempt was made to access a socket in a way forbidden by its access permissions. :AH00072: make_sock: could not bind to address
AH00451: no listening sockets available, shutting down
AH00015: Unable to open logs

The problem is that Windows 10 now comes with several extra Services that take port 80 (HTTP) and 443 (HTTPS), which Apache needs to start.

If Apache will not start (due to the above binding/socket/port issue), then one of these two Services is running on Windows 10.

  1. Web Deployment Agent Service (MsDepSvc)
  2. IIS / World Wide Web Publishing Service (W3SVC)

These services are not needed for Windows functionality and can be safely disabled.

Run ‘services.msc’, select the service, click to stop it, and then change its Startup Type from “Automatic” to “Disabled”.

If you are still not able to start Apache, check the bigger list of services that prevent Apache from starting.

Send mail through WordPress (without using SMTP plugins)

WordPress itself does not provides SMTP settings to configure in the admin area.

But there are two ways that you can send mail from WordPress:

  1. By using plugins that set up SMTP connections to outside mail servers.
  2. Or by using WordPress’ internal wp_mail() function, which defaults to using PHP’s mail() function, fully relying on PHP’s settings to handle mail.

To send mail via wp_mail(), WordPress uses an internal PHPMailer class which sets some default values.

The included PHPMailer class defaults to using PHP’s mail() function, but can also instead connect to your mail account (e.g., gmail) directly.

To use the mail() function, you’ll need to enable and configure MSMTP to establish a local SMTP proxy/forwarding to a real mail server or mail account (such as gmail).

Then edit file –


public $From = 'root@localhost';
public $Host = 'localhost';
public $SMTPAutoTLS = true;


public $From = '';
public $Host = '';
public $SMTPAutoTLS = false;

The above settings is for a local SMTP proxy such as MSMTP or for a local SMTP server.

If you want to connect to gmail directly, change “$Mailer” to “SMTP” and update settings accordingly.

Debugging SMTP Issues

Check the website’s HTTP and PHP error log files, and the general PHP error log file for logged PHP errors.

Check PHP’s mail() function log and MSMTP’s log file to make sure that email is not being rejected because the header/from is invalid.

PHP mail log – C:\WampDeveloper\Logs\Php\maillog.txt

MSMTP mail log – C:\WampDeveloper\Tools\msmtp\msmtplog.txt

Optimized WAMP Setting For Increased Performance

OS Layer

If your OS is a server edition, does not contain other software (such as active anti-virus programs), has a clean network layer, and has network drivers that are not broken, enable the use of the OS’s abilities to speed up memory access, file delivery, and network access.

Enable the use of:

1. Sending static files to the client without reading those files by using Apache directive EnableSendfile.

EnableSendfile On

2. Memory mapped files to provide a more direct access to files by using Apache directive EnableMMAP.

EnableMMAP On

This works better for delivering larger files, than smaller files.

3. OS API AcceptEx() rather than Accept() to optimize socket handling, and recycle sockets between connections, by using Apache directive AcceptFilter.

<IfVersion < 2.3>
  # Make sure this is commented out
  # Win32DisableAcceptEx
<IfVersion >= 2.3.3>
  AcceptFilter http data
  AcceptFilter https data

All the above settings are stored in file –

Save file and restart Apache for changes to take effect.

These setting can create operational problems such as: random issues with pages not being loaded or being loaded half way, Apache crashes, and in some cases performance degradation. WampDeveloper Pro defaults to turning all of these settings Off for stability and compatibility reasons, with the possible trade-off in performance.

Interfering Software

To prevent slowdowns, make sure to exclude the Apache, PHP, and MySQL processes and WAMP folder from anti-virus (and related software) scanning. The database files, the temporary folder files, and the log folder files, can update and change often – and any type of watching/reading/locking interference from outside applications will create issues.

The Windows Firewall has also been known to add a latency delay (0.5s) to requests in some circumstances (e.g., if IPv6 is enabled).

WAMP Layer

There are some general Apache, MySQL, and PHP settings that deal with resources that you can increase. But this should only be done on a server that is experiencing increasing loads (otherwise – on a web-dev box, it will just make your system more sluggish)…

Apache Worker Count

ThreadsPerChild is the number of threads Apache will spin up when it starts. Each thread can handle a separate simultaneous client.

Generally there would not be a realistic situation (for a typical website and access pattern) where more than 128 workers would be needed for a single server… If all other settings are tuned in, 128 threads can handle about 100 different clients all accessing the server within about a 3 second span. That’s allot of traffic, and a allot of resources.

Raising this value overly too much will just make each additional worker/thread take up resources.

File Config\Apache\extra\httpd-mpm.conf

ThreadsPerChild 96
ThreadLimit 128

If you check Apache’s general error log file and this message is present –

"AH00326: Server ran out of threads to serve requests. Consider raising the ThreadsPerChild setting."

Then the Apache worker count (ThreadsPerChild) should be raised (but not overly too much as each additional worker/thread will take up resources).

Also, if this message is shown –

"AH00358: Child: Process exiting because it reached MaxConnectionsPerChild. Signaling the parent to restart a new child process."

Then increase value of MaxRequestsPerChild.

On the other hand, if this message is not present, decrease the value of MaxRequestsPerChild.

This tells Apache when to recycle its workers/threads – to get rid of the memory leaks. Recycling workers/threads once per day is optimal.

MySQL Cache Size

File \Config\Mysql\my.ini

# Buffer sizes to 1/4 or 1/2 of your RAM
# For MyISAM
key_buffer_size = 512MB
# For InnoDB
innodb_buffer_pool_size = 1000MB

# Log size to 1/4 of the above innodb_buffer_pool_size
innodb_log_file_size = 256MB

The total of these caches and buffers should not exceed 2000MB when using MySQL 32 bit builds as this is about the max usable RAM allocation for a 32 bit process.

Changing the value of ‘innodb_log_file_size’ can cause some older versions of MySQL to fail to start, or for the InnoDB Engine to not load. You’ll need to move out (don’t delete just in case) file(s) Database\ib_logfile0 and ib_logfile1 (if it exists). This is a bit unclean, but if everything was flushed and shut down properly, should not be problematic.

PHP Memory Limit

This is generally not a good idea (and will not help scale the website), and only helps when a script needs more memory because it’s bad at managing it (and is crashing PHP)…

File \Config\Php\php.ini

memory_limit = 1000MB

Generally you don’t want set a value above 2000MB (slightly lower than 2GB / 2048MB) when using PHP 32 bit builds as it:
1) Begins to exhaust the memory space PHP can use (running under a 32 bit process).
2) Has been know to trigger PHP bugs.

Any script needing more than 1024MB is usually indicative of bad memory management or memory leakage by that script.

This is a value PER script.

This setting can also be overridden in the VirtualHost, the website’s .htaccess files, and in the script code itself via ini_set('memory_limit', ...). So it’s important to do a quick search to make sure nothing like that is happening.

If you check PHP’s general error log file and also the specific website’s PHP error log, and this message is present –

"PHP Fatal error: Allowed memory size of xxx bytes exhausted (tried to allocate xxx bytes) in file.php on line xxx."

Then PHP’s “memory_limit” value should be increased from the default of 256MB-512MB to somewhere between 512MB-2000MB (* this value cannot be set higher in 32bit PHP versions).

Enable PHP’s Opcode Cache

File \Config\Php\php.ini, Section: [Zend OPcache]

Un-comment Zend OPcache section. Save file. Restart Apache.

Use PHP’s Zend OPcode to cache PHP scripts as compiled objects.

Caching the PHP script files will alleviate some I/O issues, as the scripts will no longer need to be re-read and re-compiled on every request, and they will now exist as objects in memory. It’s usually good for a 50%-200% increase in handling requests/second, decreasing CPU time by 50%, and lowering script execution time… But that is for a typical wordpress website, and comparable to a system that’s currently maxing out (cpu 99%, requests/second peaked, etc)… Your particular case might be a bit different.

To exclude certain files from caching add paths to blacklist file:

Disable XDebug

File \Config\Php\php.ini, Section: [XDebug]

Make sure XDebug is not loaded, as it will slow everything down considerably (at least 2x).

MySQL Persistent Connections

Disable PHP’s MySQL persistent connections. They are never recommended and can cause all kinds of issues as user numbers increase.

File \Config\Php\php.ini, Section: [MySQL]

; Allow or prevent persistent links.

PHP FCGI Process vs. Apache Module mod_php

If Apache is crashing, try switching to PHP-FCGI, which is known to work better with these scale-related bugs and issues. When PHP-FCGI is used, PHP is ran outside of Apache in its own separate process pool.

True Caching Layer

For everything else, there is only one practical way to increase performance of a server that will produce 2x-10x results…

Use a caching layer such Apache’s mod_cache to temporarily cache output, or a front-end caching reverse proxy setup (e.g., Varnish or Squid).

Installing GeoIP Apache Module to Get Country From IP Address

Enabling, configuring, and using mod_geoip2 for Apache is very simple…

These steps will work for any Windows or Linux Apache installation, but are specific to WampDeveloper Pro (as it already contains mod_geoip2 and its configuration + databases).

Configuring mod_geoip2

Load WampDeveloper’s mod_geoip configuration by opening file httpd.conf and uncommenting line:

Include C:/WampDeveloper/Config/Apache/extra/wampd-geoip.conf

WampDeveloper’s included mod_geoip setup contains the following self-explanatory configuration:

<IfModule !mod_geoip.c>
	LoadModule geoip_module modules/

<IfModule mod_geoip.c>
	# Enable for all websites and URLs
	GeoIPEnable On
	# Turn off mod_geoip token in server signature
	GeoIPToken Off
	# Change output charset from ISO-8859-1 (Latin-1) to UTF-8 (for city names only?)
	GeoIPEnableUTF8 On
	# Set only the "GEOIP_..." environment variables
	# Default is: All
	GeoIPOutput Env
	# Use true client IP instead of the possibly bogus IP in "Forwarded For" Headers
	# note - to use IP behind trusted proxy (ex: CloudFlare), use mod_remoteip
	GeoIPScanProxyHeaders Off
	# note - If Apache is crashing, instead of GeoIPFlags: MemoryCache or IndexCache, try using: Standard
	# Load Country level databases into memory (loading into memory will increase httpd proccess size 1.5-2x)
	GeoIPDBFile C:/WampDeveloper/Tools/GeoIP/GeoIP.dat MemoryCache
	GeoIPDBFile C:/WampDeveloper/Tools/GeoIP/GeoIPv6.dat MemoryCache
	# Additional DBs loaded into memory (MemoryCache) can greatly increase httpd process size (2-5x)
	#GeoIPDBFile C:/WampDeveloper/Tools/GeoIP/GeoLiteCity.dat Standard
	#GeoIPDBFile C:/WampDeveloper/Tools/GeoIP/GeoLiteCityv6.dat Standard
	#GeoIPDBFile C:/WampDeveloper/Tools/GeoIP/GeoIPASNum.dat IndexCache
	#GeoIPDBFile C:/WampDeveloper/Tools/GeoIP/GeoIPASNumv6.dat IndexCache

Save changes to the httpd.conf file. Restart Apache.

Getting Country and Location Data From Client IP Address

When enabled, mod_geoip2 provides to Apache and PHP multiple environmental variables containing location specific data of the connecting/client IP address:

echo 'Client IP Address: '   . getenv('GEOIP_ADDR');
echo 'Client Country Code: ' . getenv('GEOIP_COUNTRY_CODE');
echo 'Client Country Name: ' . getenv('GEOIP_COUNTRY_NAME');

This data further goes down to the specific city.

Output Variables of mod_geoip2

Blocking Countries

To use GeoIP blocking, set in website’s VirtualHost or .htaccess files the following configuration, updated to include the country-codes that you want to block.

GeoIPEnable On

# to block China
# to block Russia
# ... place more countries here

Deny from env=BlockCountry

GeoIP Databases

GeoLite Legacy Databases are free and can be downloaded from:

GeoLite Legacy Databases are updated on the first Tuesday of each month.

WampDeveloper stores the referenced GeoIPDBFile databases in folder C:\WampDeveloper\Tools\GeoIP, and you can use Windows Tasks Scheduler to automatically wget or cURL [both tools are provided] to get updated databases each new month.


1. “mod_geoip2″ (v2) is technically version 1.2.x.

2. Use “GeoIP Legacy” .dat databases, not “GeoLite2″ .mmdb databases (they are for mod_maxminddb).

3. mod_geoip module is only provided for Apache 2.4 VC11 32 and 64 bit builds, and Apache 2.2 VC9 32 bit builds.

4. Downloadable mod_geoip builds can be found at ApacheHaus…
mod_geoip-1.2.9 (rc):

5. Documentation:
mod_geoip2 configuration documentation –
mod_geoip2 changelog –