There are many robots scanning sites for vulnerabilities, to gain control or exploit the servers. Most of them come from China and Russia ip’s.
Here I explain an easy way to block them using the Ubuntu Firewall ufw.
If you use a CMS like WordPress and you know there are extensions that have had security exploits, for example, wp-file-manager then you can search directly for this request in Apache Access Logs.
For example:
cat /var/log/apache2/blog_carlesmateo_com-access.log | grep "wp-file-manager" | awk '{ print $1; }' | sort -u >> 2020-10-03-offending-ips.txt
cat /var/log/apache2/blog_carlesmateo_com-access.log.1 | grep "wp-file-manager" | awk '{ print $1; }' | sort -u >> 2020-10-03-offending-ips.txt
zcat /var/log/apache2/blog_carlesmateo_com-access.log.2.gz | grep "wp-file-manager" | awk '{ print $1; }' | sort -u >> 2020-10-03-offending-ips.txt
In the example we look for the access.log file, for the rotated access.log.1 and for the rotated and compressed access.log.2.gz. We use the tool zcat which does a cat over a compressed file.
If we don’t expect to have anybody posting to our xmlrpc Service, we can check for the offending Ip’s by doing:
cat /var/log/apache2/blog_carlesmateo_com-access.log | grep "POST /xmlrpc.php" | wc --lines
2490
In my case I have 2490 request just in the last log.
cat /var/log/apache2/blog_carlesmateo_com-access.log | grep "POST /xmlrpc.php" |awk '{ print $1; }' | sort -u | wc --lines
Interested in how many Ip’s are launching those requests, you can see how many different Ip’s are those:
cat /var/log/apache2/blog_carlesmateo_com-access.log | grep "POST /xmlrpc.php" |awk '{ print $1; }' | sort -u | wc --lines
145
And to add those Ip’s to the offending Ip’s list:
cat /var/log/apache2/blog_carlesmateo_com-access.log | grep "POST /xmlrpc.php" | awk '{ print $1; }' | sort -u >> 2020-10-03-offending-ips.txt
I can also check for repeated requests in the logs:
cat /var/log/apache2/blog_carlesmateo_com-access.log | awk '{ print $7; }' | sort | uniq -c | sort -r | less
That shows me some requests legit and others that are not:
2532 /xmlrpc.php
209 /wp-login.php
205 /wp-admin/admin-ajax.php
84 /
83 *
48 /robots.txt
21 /favicon.ico
16 /wp-login.php?redirect_to=https%3A%2F%2Fblog.carlesmateo.com%2Fwp-admin%2F&reauth=1
15 /wp-includes/js/jquery/jquery.js?ver=1.12.4-wp
14 /wp-includes/css/dist/block-library/theme.min.css?ver=5.5.1
14 /wp-includes/css/dist/block-library/style.min.css?ver=5.5.1
14 /wp-content/themes/2012-carles/style.css?ver=5.5.1
14 /wp-content/plugins/contact-form-7/includes/js/scripts.js?ver=5.2.2
14 /wp-content/plugins/captcha/css/front_end_style.css?ver=4.4.5
13 /wp-includes/css/dashicons.min.css?ver=5.5.1
13 /wp-content/themes/2012-carles/css/blocks.css?ver=20181230
13 /wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.2.2
12 /wp-includes/js/wp-embed.min.js?ver=5.5.1
12 /wp-includes/images/w-logo-blue-white-bg.png
12 /wp-content/themes/2012-carles/js/navigation.js?ver=20140711
11 /wp-includes/js/wp-emoji-release.min.js?ver=5.5.1
11 /wp-content/plugins/captcha/css/desktop_style.css?ver=4.4.5
11 /feed/
11 /contact/
10 /wp-comments-post.php
10 /?author=1
9 /2016/06/30/creating-a-content-filter-for-postfix-in-php/
9 /2014/10/13/performance-of-several-languages/
8 /wp-includes/js/comment-reply.min.js?ver=5.5.1
8 /wp-content/plugins/captcha/js/front_end_script.js?ver=5.5.1
8 /e/admin/index.php
8 /e/admin/
7 /wp-login.php?action=register
7 /current-projects/
7 //xmlrpc.php
6 /.env
5 /2019/08/12/a-sample-forensic-post-mortem-for-a-iscsi-initiator-client-that-had-connectivity-problems-to-the-server/
5 /2017/03/26/csort-multithread-versus-quicksort-java/
4 /wp-json/wp/v2/types/wp_block?_locale=user
4 /wp-json/wp/v2/blocks?per_page=100&_locale=user
4 /wp-admin/
4 /diguo/index.php
4 /diguo/
4 /category/web-development/
4 /category/news-for-the-blog/
3 /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
3 /mt-notation-for-python/
3 /ebk/index.php
3 /ebk/
3 /comments/feed/
3 /bf/index.php
3 /bf/
3 /beifen/index.php
3 /beifen/
3 /Ebak/index.php
3 /Ebak/
3 /Bak/index.php
3 /Bak/
3 /2020/09/21/how-to-recover-access-to-your-amazon-aws-ec2-instance-if-you-loss-your-private-key-for-ssh/
3 /2020/08/23/adding-a-ramdisk-as-slog-zil-to-zfs/
3 /2019/07/03/adding-my-server-as-docker-with-php-catalonia-framework-explained/
3 /2019/06/25/some-handy-tricks-for-working-with-zfs/
3 /2015/02/01/stopping-definitively-the-massive-distributed-dos-attack/
2 /ycadmin/login.php?gotopage=%2Fycadmin%2Findex.php
2 /ueditor/net/controller.ashx
2 /sql_beifen/index.php
2 /sql_beifen/
2 /sql/index.php
2 /sql/
2 /dgbf/index.php
2 /dgbf/
2 //xmlrpc.php?rsd
2 //.env
1 /wp-login.php?registration=disabled
1 /wp-login.php?action=lostpassword
1 /wp-json/wp/v2/users/me?_locale=user
1 /wp-json/wp/v2/users/?who=authors&per_page=100&_locale=user
1 /wp-json/wp/v2/taxonomies/post_tag?context=edit&_locale=user
1 /wp-json/wp/v2/taxonomies/category?context=edit&_locale=user
1 /wp-json/wp/v2/tags?per_page=100&orderby=count&order=desc&_fields=id%2Cname&search=ufw&_locale=user
You can identify manually what are attacks, and what are legit requests.
After you have your definitive list of offending Ip’s (and make sure you didn’t introduce yours accidentally), then you can execute the second part of the script:
echo '#!/bin/bash' > add_ufw_rules.sh
i_COUNTER_RULE=0; for s_OFFENDING_IP in $(cat 2020-10-03-offending-ips.txt); do i_COUNTER_RULE=$((i_COUNTER_RULE+1)); echo "ufw insert $i_COUNTER_RULE deny from $s_OFFENDING_IP to any" >> add_ufw_rules.sh; done
echo "ufw status numbered" >> add_ufw_rules.sh
echo "sudo ufw allow OpenSSH" >> add_ufw_rules.sh
echo "sudo ufw allow 22/tcp" >> add_ufw_rules.sh
echo 'sudo ufw allow "Apache Full"' >> add_ufw_rules.sh
echo "sudo ufw enable" >> add_ufw_rules.sh
Then you less your file add_ufw_rules.sh to see everything is Ok:
#!/bin/bash
ufw insert 1 deny from 40.79.250.88 to any
ufw insert 2 deny from 52.173.148.212 to any
ufw insert 3 deny from 94.103.85.175 to any
ufw insert 4 deny from 40.79.250.88 to any
ufw insert 5 deny from 78.85.208.240 to any
ufw insert 6 deny from 80.82.68.173 to any
ufw insert 7 deny from 188.165.230.118 to any
ufw insert 8 deny from 195.201.117.103 to any
ufw insert 9 deny from 40.79.250.88 to any
ufw insert 10 deny from 5.135.138.188 to any
ufw insert 11 deny from 51.116.189.135 to any
...
ufw insert 223 deny from 95.173.161.167 to any
ufw insert 224 deny from 95.84.228.227 to any
ufw status numbered
sudo ufw allow OpenSSH
sudo ufw allow 22/tcp
sudo ufw allow "Apache Full"
sudo ufw enable
Then you simply give permissions with chmod +x add_ufw_rules.sh and run the script to apply.
It’s up to you to turn on the Firewall logging:
sudo ufw logging on