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 –

Running PHP exec() Shell Functions On WAMP

WAMP servers (such as WampDeveloper Pro) usually do not restrict executions of PHP functions – such as exec() and shell_exec(). You can verify this by checking the website’s Apache and PHP error log files.

If you are able to run your commands manually from the command-line, but not via WAMP, than the user the Apache Service runs as does not have the needed permissions to execute your commands and binaries (nor interact with the desktop if it is GUI related).

If you create a test.php file and place this code inside:

echo exec('whoami');

When run via a URL, Apache will output:

nt authority\system

But if you run “whoami” from the command-line yourself, it will output:


The user difference is why those commands do not run via Apache.

To execute privileged shell commands via Apache, you’ll have to run “services.msc”, select the Apache service, and change the “Log On” account From “Local System” to another user/account.

To avoid permissions issues, create a user in the Administrators group, and make sure to set the user’s password (as password-less accounts are “unauthenticated” which causes further issues).

Later on, once you verify that everything is working, you can fine-tune the account’s permissions. And check if what you are trying to execute requires Admin privileges.

WordPress – Changing the Temp Directory

A user was trying to secure different WordPress installations from each other (and the rest of WAMP) by setting each to use a different Temp directory:

We currently host 4 different WordPress websites using WAMP. Is it possible to configure the temp directory for each site separately, perhaps as a subdirectory in C:\WampDeveloper\Temp directory?

This way a compromised WordPress base will not spread a downloaded payload or script to another base (as normally all PHP scripts share a common Temp folder).

Checking the WordPress source-code, WordPress uses this function to find and derive the path of the temporary directory:

The first thing get_temp_dir() checks for is this PHP runtime constant:


If you edit the WordPress configuration file wp-config.php, and place this line in, it should set the new temporary folder:

define('WP_TEMP_DIR', 'C:\WampDeveloper\Temp\WP1');

The above example is for a sub-directory “WP1″ under the original WampDeveloper Temp directory (on drive C). This sub-directory will need to be created manually.

If you use a path outside the \WampDeveloper\Temp directory, note that:
1. You could have issues with Apache not being able to read/write into it (a network share directory, required permissions, etc).
2. Also, PHP’s “open_basedir” setting (it is not enabled by default) would need to be updated in the website’s VirtualHost or .htaccess files to allow the script access to the path (or in php.ini if using PHP-FCGI).

If you are using older WordPress plugins that do not use the proper WordPress function get_temp_dir() to get the temp dir, but instead rely on the environmental variables, you can also add a second line into wp-config.php to set env variable TMPDIR:

putenv('TMPDIR=' . 'C:\WampDeveloper\Temp\WP1');

Laravel – Key size not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported.

The new version of PHP 5.6+ is now enforcing proper key sizes. If your Laravel APP_KEY is not the proper (supported) character length, you will get the following error:

mcrypt_decrypt(): Key of size 5 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported.

There are 2 ways to fix this:

A) “Pad” the key to a valid size. This will preserve your existing encrypted data such as: any data that was saved with Crypt::encrypt() in the database, passwords saved with Hash::make() [note – there is conflicting information on if the key is used during password hashing and storage], and current sessions.

B) Or generate a new key and lose your previously encrypted data:

php artisan key:generate

Pad Laravel APP_KEY to Next Supported Length

To preserve your existing encrypted data, manually “pad” your existing key to the next valid size (16, 24, 32 characters). This is how invalid size keys were handled internally by the PHP mcrypt_decrypt() function before the change in PHP 5.6+…

Previously keys and IVs were padded with ‘\0′ bytes to the next valid size.

If it is 10 characters, pad it to 16.
If it is 20 characters, pad it to 24.
If it is 25 characters, pad it to 32.


1. Open your Laravel configuration file:


2. Find line:

'key' => env('APP_KEY', 'SomeRandomString'),

The above line attempts to read the value of Laravel’s environmental variable APP_KEY (as defined in Laravel’s .env file), and if unable to do so, uses the quoted value.

3. Count the number of characters the key value is (without the quotes), and make it valid-sized by adding null bytes to the end. You will need to replace the quotes that surround the key value from single quotes to double quotes – so PHP interprets the null bytes correctly.

For example, if your key is “12345”, than it is 5 characters long, and it needs to be made 16 characters long like so:


With the above app.php line like so:

'key' => env('APP_KEY', "12345\0\0\0\0\0\0\0\0\0\0\0"),


The above key value is also stored in Laravel’s .env file (which itself usually acts as the primary source for APP_KEY).

1. Open your Laravel .env file:


2. Find line:


3. Update it to the padded value, surrounded by double quotes like so:



As an alternative, you can use the PHP function str_pad to automatically do the above manual padding. For example, to pad a 17-23 character length key to 24:

str_pad($str, 24, "\0", STR_PAD_RIGHT);

Also the PHP function chr can be used to return the null byte instead of specifying it with special escape sequences:


Laravel uses PHPDotEnv (3rd-party library) to read the .env file and load the environmental variables. PHPDotEnv uses its own basic text/string format – and you cannot embed PHP code into the .env file. If you are unable to place the null-byte padded value into the .env file, you can comment out (#) the APP_KEY line so Laravel uses the default/fallback value from the app.php file.

The issue is referenced here: mcrypt_decrypt() throws error when PHP 5.6 is used if key is not 32 characters #6722

Laravel – No supported encrypter found. The cipher or key length are invalid.

A user was trying to install Laravel under WAMP and got the following error:

RuntimeException in compiled.php line 6904: No supported encrypter found. The cipher and / or key length are invalid.

Looking at the Laravel installation instructions, the only WampDeveloper specific change that would need to be done is to load the PHP sockets extension:

1. Open file C:\WampDeveloper\Config\Php\php.ini (via Notepad)

2. Find this line and uncomment it (remove front “;”) –


3. Save file. Restart Apache.

All the other Laravel required PHP extensions and Apache modules under WampDeveloper are loaded and enabled by default.

The above error seems to be Laravel-specific (rather than having something to do with WAMP) and here is how to fix it…

1. Make sure that in Laravel’s config\app.php file, the 'cipher' is defined as so:

'cipher' => 'AES-256-CBC',

2. Make sure Laravel’s “.env” file exists. If this file does not exist, open the command-line (run cmd.exe), change the command-line’s “working directory” to Lavavel’s installed-to path, and create this file from the provided example template file:

cd \path\to\laravel\folder
cp .env.example .env

The first line (“C:”) changes to drive “C”, the second line changes to the path (on C)… substitute-in for your Laravel installed location. The third line makes a properly-named copy of the base example file. Because this file starts with a period, it’s much simpler to make a copy using the command-line (otherwise you’ll run into issues).

3. The cause of the issue is – the above cipher “AES-256-CBC” needs a 32 character key, but the default random key is only 16 characters long.

Generate a new 32 character string for the key by running (from cmd.exe):

php artisan key:generate

The command should automatically update the app.php file (and also the .env file) with a new proper-size key, and output something similar to this afterwards:

Application key [g8MOZ9dYU4ap5F12m95PIPAA5AJG3Sh6] set successfully.

4. Verify that the above key is now in Laravel's .env file:


If it's not, manually add it in as shown above (substitute in your key, and without the brackets).

* On another unrelated but similar cause, if this is happening sometime after a successful installation - after your app is fully installed and running - then it is possible that the APP_KEY was changed and now the encrypted data cannot be decrypted. In this case, unless you can revert to the previous key, you'll have to either delete the encrypted data or start over.

MySQL ERROR 1045 (28000): Access denied for user ‘db_user_name’@’localhost’

I have software that requires direct access to the MySQL database. If I run it on the same computer as WAMP it works, but if I access the database with this software from another computer, it then reports error:

MySQL ERROR 1045 (28000): Access denied for user 'db_user_name'@'localhost' (using password: YES)

Create the same database user (i.e., with the same name + password as the existing user) in MySQL (via \phpmyadmin), except set the “Host:” field to either the connecting remote IP address, or to “%” (which means any IP can connect).

This way you’ll be able to use this user to access the database from (Host:, and also from an outside system (Host:%).

Also make sure that you have already:

  • Re-bound MySQL from IP to
  • Opened incoming port 3306 requests in Windows Firewall (and removed any existing blocking MySQL rules).
  • Port-forwarded port 3306 in the Router from WAN:3306 to LAN-IP:3306 (if accessing from outside the LAN).

And that this database user has all permissions granted on the specific database(s), and the outside application is using the proper: IP, database name, user name, user password – to establish the connection.

If you have the mysql client on the remote system, you can also manually test this from the command-line via:

mysql -u db_user_name -p -h -P 3306

Accessing MySQL or phpMyAdmin From Outside

Running .NET 3.5 App on .NET 4.5 of Windows 8 and Server 2012

There is a very easy way to run .NET 3.5 applications under .NET 4.5 (and 4.0), without having .NET 3.5 installed…

Edit the application’s app.exe.config file:


And within the “<configuration>” section, add in the support for runtime v4:

  <supportedRuntime version="v2.0.50727"/>
  <supportedRuntime version="v4.0"/>

The above configuration will have the system use .NET 3.5 if it finds it [.NET v3.5 uses runtime “v2.0″], otherwise it will use .NET 4.0 or 4.5 (which use runtime “v4.0″).

And if your application is having issues (e.g., nothing shows on-screen except the application border with a background color inside) on a Windows 7 + (or Server 2008 +) system with .NET v4, that also has .NET 3.5 enabled, try placing the <suppportedRuntime version="v4.0"/> line above the 2.0 line – so it tries to use .NET v4 first… As some systems with both .NET v4 and v3.5 have the latter in a corrupted state.

Whether this works depends on whether the code used in the application is compatible with the changes that were made in the newer releases of .NET version and runtime. Most applications will be 100% compatible with the higher version.

Related Information

1. Graph of the default .NET version that shipped with the Windows OS version:
Windows .NET Versions

2. Microsoft documentation on the above configuration changes: How to Configure an App to Support .NET Framework 4 or 4.5

3. Microsoft documentation on which versions of .NET that can be installed per Windows OS version: .NET Framework Versions and Dependencies