Block UserAgent libwww-perl and test

If you want to apply this globally, edit /etc/httpd/conf/httpd.conf (Centos). Otherwise, just modify the related vhost config file, adding the following:

ServerSignature Off
SetEnvIfNoCase User-Agent "^libwww-perl" bad_bot
<Location />
Order allow,deny
Allow from all
Deny from env=bad_bot
</Location>

How to test:

Check if the site responds:

$ curl -I http://www.mywebsite.com
HTTP/1.1 200 OK
Date: Thu, 13 Nov 2014 17:12:16 GMT
Server: Apache
Last-Modified: Thu, 13 Nov 2014 16:00:35 GMT
ETag: "1fa5dc-9dd5-507bf9cd66ec0"
Accept-Ranges: bytes
Content-Length: 40405
Vary: Accept-Encoding,Cookie
Content-Type: text/html; charset=UTF-8

 

Check if the agent libwww-perl is allowed or forbidden:

$ curl -A "libwww-perl" -I http://www.mywebsite.com
HTTP/1.1 403 Forbidden
Date: Thu, 13 Nov 2014 17:12:51 GMT
Server: Apache
Vary: Accept-Encoding
Content-Type: text/html; charset=iso-8859-1

 

Check if using Mozilla as agent works or not:

$ curl -A "Mozilla/5.0 (iPhone; U; CPU PerformanceOptimized iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5" -I http://www.mywebsite.com
HTTP/1.1 200 OK
Date: Thu, 13 Nov 2014 17:13:27 GMT
Server: Apache
Last-Modified: Thu, 13 Nov 2014 16:00:35 GMT
ETag: "1fa5dc-9dd5-507bf9cd66ec0"
Accept-Ranges: bytes
Content-Length: 40405
Vary: Accept-Encoding,Cookie
Content-Type: text/html; charset=UTF-8

 

Source IP in Apache logs

If your server is under a load balancer, you might see HTTP requests coming from the Load Balancer’s IP instead of the actual visitor. Generally, load balancers are “recording” the original source IP in the X-Forwarded-For header. This means that this is the header that we need to log in our Apache logs to get the information that we want.

Here how to make this happen:

Default rule:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

Modified rule that includes the X-Forwarded-For definition:

LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined


==============================================

>> Best way:


On httpd.conf:
=====================
SetEnvIfNoCase X-Forwarded-For "." from_proxy=1

LogFormat "%{CF-Connecting-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" forwarded
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
=======================

On vhost.conf
============================
CustomLog /var/log/httpd/vhost-access.log forwarded env=from_proxy
CustomLog /var/log/httpd/vhost-access.log combined env=!from_proxy
============================

 

Source: https://community.rackspace.com/products/f/25/t/211

Apache Rewrite rules

Rewrite rules examples:

This can be added in vhost configuration OR in .htaccess file

How to rewrite all web request on my site without www to www.domain.com

RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule (.*) http://www.example.com$1 [R,L]

 

How to redirect all web requests on port 80 (or HTTP) to port 443 (HTTPS)

RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [L,R]

 

How to disable TRACE and TRACK methods on Apache

RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]

 

How to exclude mod_status from being rewritten by existing rules (placed before the problem rule)

RewriteCond %{REQUEST_URI} !=/server-status

 

How do I redirect all web requests on www.mysite.net/web to www.mysite.net/sect1/web

RewriteCond %{http_host} ^[www\.]*example\.com
RewriteRule ^web(/)?$ /sect1/web [R=301,L]

 

Rewrite all non-www to www

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

 

Force all URLs to be lowercase

RewriteEngine On
RewriteMap lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]

 

WordPress notes

Reset Admin Password

UPDATE wp_users SET user_pass=MD5('newpassword123') WHERE ID = 1;

Create New Admin account

mysql> INSERT INTO `wp_users` (`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_status`, `display_name`) VALUES ('username', MD5('password'), 'friendly-name', '[email protected]', 'http://example.com', '0', 'Your Name');
mysql> SELECT LAST_INSERT_ID() INTO @userid;INSERT INTO `wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, @userid, 'wp_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}'), (NULL, @userid, 'wp_user_level', '10');

Show error in case white screen appears
Try adding this line to wp-config.php to see the errors on the page:

define( 'WP_DEBUG', true );

Change the site URL

mysql> SELECT * FROM wp_options WHERE option_name = 'siteurl' OR option_name = 'home' ;
mysql> UPDATE wp_options SET option_value = 'http://staging.mysite.com' WHERE option_name = 'siteurl' OR option_name = 'home' ;

Disable all plugins

mysql> UPDATE wp_options SET option_value = 'a:0:{}' WHERE option_name = 'active_plugins';

Show users and Privileges

mysql> SELECT user_login,user_registered,meta_value FROM wp_users INNER JOIN wp_usermeta ON wp_users.id = wp_usermeta.user_id and meta_key = 'wp_capabilities';
+---------------+---------------------+---------------------------------+
| user_login | user_registered | meta_value |
+---------------+---------------------+---------------------------------+
| administrator | 2013-12-21 10:36:30 | a:1:{s:13:"administrator";b:1;} |
| author | 2014-11-25 15:50:34 | a:1:{s:6:"author";b:1;} |
| editor | 2014-11-25 15:51:18 | a:1:{s:6:"editor";b:1;} |
| contributor | 2014-11-25 15:51:48 | a:1:{s:11:"contributor";b:1;} |
| subscriber | 2014-11-25 15:52:11 | a:1:{s:10:"subscriber";b:1;} |
+---------------+---------------------+---------------------------------+
5 rows in set (0.01 sec)

 

Update theme to Twenty Fourteen

mysql> UPDATE wp_options SET option_value = 'twentyfourteen' WHERE option_name = 'template' OR option_name = 'stylesheet';
mysql> UPDATE wp_options SET option_value = 'Twenty Fourteen' WHERE option_name = 'current_theme';

 

Administration Over SSL
Add the below lines to the wp-config.php file above the ‘/* That’s all, stop editing! Happy blogging. */’ line

define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);

This ensures the login AND the administration is done over SSL

You could also use the below .htaccess:

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)\ HTTP/ [NC]
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://mysite.com%{REQUEST_URI}%{QUERY_STRING} [R=301,QSA,L]

 

Find out how many SQL queries are executed every time a page is loaded.
Add the below to one of the theme files, I usually add to footer.php

if ( current_user_can( 'manage_options' ) ) {
echo $wpdb->num_queries . " SQL queries performed.";
} else {
// Uncomment the below line to show SQL queries to everybody
// echo $wpdb->num_queries . " SQL queries performed.";
}

 

Here are some configuration parameters you can add to your wp-config.php file for FTP.

define('FS_METHOD', 'direct'); 
/*
forces the filesystem method. It should only be "direct", "ssh2", "ftpext", or "ftpsockets". Generally, you should only change this if you are experiencing update problems. If you change it and it doesn't help, change it back/remove it. Under most circumstances, setting it to 'ftpsockets' will work if the automatically chosen method does not.

(Primary Preference) "direct" forces it to use Direct File I/O requests from within PHP, this is fraught with opening up security issues on poorly configured hosts, This is chosen automatically when appropriate.
(Secondary Preference) "ssh2" is to force the usage of the SSH PHP Extension if installed
(3rd Preference) "ftpext" is to force the usage of the FTP PHP Extension for FTP Access, and finally
(4th Preference) "ftpsockets" utilises the PHP Sockets Class for FTP Access.
*/
define('FTP_BASE', '/var/www/vhosts/example.com/httpdocs/'); // is the full path to the "base"(ABSPATH) folder of the WordPress installation. 
define('FTP_CONTENT_DIR', '/var/www/vhosts/example.com/httpdocs/wp-content/'); // is the full path to the wp-content folder of the WordPress installation.
define('FTP_PLUGIN_DIR ', '/var/www/vhosts/example.com/httpdocs/plugins/'); // is the full path to the plugins folder of the WordPress installation. 
define('FTP_PUBKEY', '/var/www/vhosts/example.com/httpdocs/.ssh/id_rsa.pub'); // is the full path to your SSH public key. 
define('FTP_PRIKEY', '/var/www/vhosts/example.com/httpdocs/.ssh/id_rsa'); // is the full path to your SSH private key. 
define('FTP_USER', 'FTPusername'); // is the FTP username
define('FTP_PASS', 'FTPpassword'); // is the password for the FTP User
define('FTP_HOST', 'localhost'); // FTP Host - usually localhost.
define('FTP_SSL', false); // This is for "Secure FTP" not for SFTP.

xmlrpc.php

I’d recommend restricting xmlrpc.php POSTs to only IPs that need it by adding the following rules to the top of your .htaccess file, updating accordingly the line ‘allow from’ with a list of IPs space separated or simply completely remove that line to block its execution:

# ----------------------------------------------------
# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
allow from 123.123.123.123
</Files>
# ----------------------------------------------------

 

Apache 2.2 + PHP-FPM on Centos

WITHOUT disabling MOD_PHP in Apache

>> Compile module:
yum -y install httpd-devel gcc
mkdir /tmp/fastcgi
cd /tmp/fastcgi
wget https://github.com/whyneus/magneto-ponies/raw/master/mod_fastcgi-SNAP-0910052141.tar.gz
tar -zxf mod_fastcgi*
cd mod_fastcgi-*
make -f Makefile.AP2 top_dir=/usr/lib64/httpd
cp .libs/mod_fastcgi.so /usr/lib64/httpd/modules/

>> Enable the module:
echo "LoadModule fastcgi_module /usr/lib64/httpd/modules/mod_fastcgi.so" > /etc/httpd/conf.d/fastcgi.conf


>> Install php-fpm and create pools like this:
[$USER]
listen = /dev/shm/$USER-php5-fpm.sock
user = $USER
group = $USER
listen.owner = $USER
listen.group = apache
listen.mode = 0666
pm = dynamic
pm.max_children = 35
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 25
slowlog = /var/log/php-fpm/$USER-slow.log
php_admin_value[error_log] = /var/log/php-fpm/$USER-error.log
php_admin_flag[log_errors] = on


>> Add this in the VHOST configuration (before the end of </VirtualHost>)
FastCGIExternalServer /dev/shm/$USER-php.fcgi -socket /dev/shm/$USER-php5-fpm.sock -flush -idle-timeout 1800
AddHandler php-fpm .php
Action php-fpm /php.fcgi
Alias /php.fcgi /dev/shm/$USER-php.fcgi
DirectoryIndex index.php
<FilesMatch "\.php$">
    SetHandler php-fpm
</FilesMatch>


>> Double check php.ini for 'session.save_path'. 
session.save_path = "/tmp"
;session.save_path = "/var/lib/php/session"

 

Linux Firewall notes

IPTABLES GENERIC

>> Allow port 80 ONLY to private interface for Cloud Load Balancer
-A INPUT -i eth1 -p tcp -m conntrack --ctstate NEW -m tcp --dport 80 -j ACCEPT

>> Block whole subnet
# iptables -I INPUT -s xxx.xxx.xxx.0/24 -j DROP

>> Allow specific IP only
iptables -I INPUT -p tcp -s YourIP --dport 22 -j ACCEPT

>> Delete rules

iptables -vnL --line-numbers

iptables -D <chain> /et<rule_number>
iptables -D INPUT 4

-A INPUT -s <SOURCE_NETWORK/32> -p tcp -m tcp --dport 21 -m comment --comment "FTP port open" -j ACCEPT
-A INPUT -s <SOURCE_NETWORK/32> -p tcp -m multiport --dports 60000:65000 -m comment --comment "FTP passive mode ports" -j ACCEPT

 


UBUNTU – UFW

service ufw status

ufw allow 80

ufw allow from <IP> to any port <port>

>> Allow network range
ufw allow 192.168.1.0/24

>> Delete rule
ufw status numbered
ufw delete <rule_number>

>> Allow port 80 only on eth1
ufw allow in on eth1 to [eth1 ip addr] port 80 proto tcp
# ufw allow from <SOURCE_IP>&nbsp;to any port 25
Rule added

# ufw delete allow from <SOURCE_IP> to any port 25
Rule deleted

ufw insert 1 allow from <ip address>

ufw deny from <ip address>
ufw deny from <ip address/24>

https://help.ubuntu.com/community/UFW

 


CENTOS / RH – Firewalld

Saved rules in: /etc/sysconfig/iptables

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<SOURCE_IP>" port port="10000" protocol="tcp" accept'

firewall-cmd --reload

firewall-cmd --list-all

firewall-cmd --add-service http --permanent
firewall-cmd --add-service https --permanent
systemctl restart firewalld.service
firewall-cmd --list-services

>> Add manual rule in firewalld

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -s 192.168.3.0/24 -m comment --comment "NFS Network" -j ACCEPT

>> Remove manual added rule in firewalld
vim /etc/firewalld/direct.xml

 

Linux ACL examples

Group permissions are NO LONGER related to group. It’s a MASK!

# setfacl -R -m u:apache:rwx html/
# getfacl html/
# file: html/
# owner: root
# group: root
user::rwx
user:alphausr:rwx
user:caesar:rwx
group::r-x
mask::rwx
other::r-x

To remove ACL as this is a temporary user and reinstate alphausr;

cd /var/www/; setfacl -R -b html/; setfacl -R -m u:alphausr:rwx html/


DEFAULT ACL
# setfacl -m d:u:apache:rwx html/

BACKUP
# getfacl -R /var/www/html/ > /root/html.perm

RESTORE (need to be in / )
# cd /
# setfacl –restore=/root/html.perm


ACL for WordPress

APACHE_ROOT=/var/www/vhosts/
SITE=mydomain.com
USERNAME=ftpuser

cd $APACHE_ROOT
setfacl -m d:u:apache:rwx .
setfacl -R -m u:apache:rwx .

find . -type d | xargs chmod 775
find . -type f | xargs chmod 664

chown -R $USERNAME $SITE

getfacl $SITE
# file: document_root
# owner: <username> <<<<<<< check this
# group: root
user::rwx <<<<<<< this
user:apache:rwx <<<<<<< and this 🙂
group::rwx
mask::rwx
other::r-x