{"id":6360,"date":"2020-07-11T16:05:34","date_gmt":"2020-07-11T13:05:34","guid":{"rendered":"https:\/\/kifarunix.com\/?p=6360"},"modified":"2024-03-14T22:12:52","modified_gmt":"2024-03-14T19:12:52","slug":"restrict-access-to-wordpress-login-page-to-specific-ips-with-libmodsecurity","status":"publish","type":"post","link":"https:\/\/kifarunix.com\/restrict-access-to-wordpress-login-page-to-specific-ips-with-libmodsecurity\/","title":{"rendered":"Restrict Access to WordPress Login Page to Specific IPs with libModSecurity"},"content":{"rendered":"\n<p>In this tutorial, we are going to learn how to restrict access to WordPress login page to specific IPs with libModSecurity. libModSecurity&nbsp;is also known as <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/www.modsecurity.org\/about.html\" target=\"_blank\" rel=\"noreferrer noopener\">ModSecurity version 3.0<\/a>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote td_pull_quote td_pull_center is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>ModSecurity is an open source, cross-platform web application firewall (WAF) module <em>developed by Trustwave&#8217;s SpiderLabs.<\/em> Known as the &#8220;Swiss Army Knife&#8221; of WAFs, it enables web application defenders to gain visibility into HTTP(S) traffic and provides a power rules language and API to implement advanced protections.<\/em><\/p>\n\n\n\n<p>It has a robust event-based programming language which provides protection from a range of attacks against web applications and allows for HTTP traffic monitoring, logging and real-time analysis.<\/p>\n<\/blockquote>\n\n\n\n<p>Are you using WordPress and looking for a professional WordPress website builder? Look no further since <a href=\"https:\/\/trk.elementor.com\/8uczdzzsxgza-webcreatorsred\" target=\"_blank\" rel=\"noreferrer noopener\">Elementor can help you create beautiful pages<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#what-can-mod-security-do\">What Can ModSecurity Do?<\/a><\/li><li><a href=\"#restrict-specific-i-ps-to-access-word-press-login-page-with-mod-security\">Restrict Specific IPs to Access WordPress Login Page with ModSecurity<\/a><ul><li><a href=\"#install-and-setup-word-press-site\">Install and Setup WordPress site<\/a><\/li><li><a href=\"#install-and-setup-lib-mod-security-on-cent-os-8\">Install and Setup LibModSecurity on CentOS 8<\/a><\/li><li><a href=\"#restrict-access-to-word-press-login-page-to-specific-i-ps\">Restrict Access to WordPress Login Page to Specific IPs<\/a><ul><li><a href=\"#create-custom-rules-to-restrict-access-to-word-press-login-page\">Create Custom Rules to Restrict Access to WordPress Login Page<\/a><\/li><li><a href=\"#create-a-rule-to-allow-access-to-word-press-login-page-uri-wp-login-php-from-specific-ip-addresses\">Create a Rule to Allow Access to WordPress login page, (URI, wp-login.php) from Specific IP addresses.<\/a><\/li><li><a href=\"#create-a-rule-to-deny-any-access-to-word-press-login-page\">Create a Rule to Deny Any Access to WordPress login page<\/a><\/li><\/ul><\/li><li><a href=\"#configure-mod-security-to-process-custom-rules\">Configure ModSecurity to Process Custom Rules<\/a><\/li><li><a href=\"#restart-apache\">Restart Apache<\/a><\/li><li><a href=\"#testing-access-to-word-press-login\">Testing Access to WordPress Login<\/a><\/li><li><a href=\"#related-tutorials\">Related Tutorials<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-can-mod-security-do\">What Can ModSecurity Do?<\/h2>\n\n\n\n<p>Below are some of the features provided by ModSecurity WAF:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Real-time application security monitoring and access control<\/li>\n\n\n\n<li>Full HTTP traffic logging<\/li>\n\n\n\n<li>Continuous passive security assessment<\/li>\n\n\n\n<li>Web application hardening<\/li>\n\n\n\n<li>Due to its ability to parse XML and apply XPath expressions with its ability to proxy requests, it can be used as an XML web service router.<\/li>\n\n\n\n<li>HTTP Protocol Protection<\/li>\n\n\n\n<li>Real-time Blacklist Lookups<\/li>\n\n\n\n<li>HTTP Denial of Service Protections<\/li>\n\n\n\n<li>Generic Web Attack Protection<\/li>\n\n\n\n<li>Error Detection and Hiding<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"restrict-specific-i-ps-to-access-word-press-login-page-with-mod-security\"><a href=\"#restrict-wp-login-access-with-libmodsecurity\">Restrict Specific IPs to Access WordPress Login Page with ModSecurity<\/a><\/h2>\n\n\n\n<p>WordPress login pages are always under brute force attacks with the malicious actors always up-to try any combination of multiple authentication credentials against your WordPress with the aim of getting access to it.<\/p>\n\n\n\n<p>There a number of methods which you can use to protect your WordPress login page against these attacks including;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Enabling basic web server http authentication.<\/li>\n\n\n\n<li>Restricting access to WordPress directories from specific IP addresses on the web server configurations<\/li>\n\n\n\n<li>Using secure plugins that masks the WordPress authentication URLs<\/li>\n\n\n\n<li>Using non-common usernames such as admin, for any user account<\/li>\n\n\n\n<li>Using complex and unique, non-dictionary passwords for logins.<\/li>\n\n\n\n<li>etc.<\/li>\n<\/ul>\n\n\n\n<p>All these methods are fine. However, you can as well be able to use ModSecurity to protect your WordPress Login pages against these attacks, and that is what this tutorial is all about.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"install-and-setup-word-press-site\"><a href=\"#install-and-setup-wordpress-site\">Install and Setup WordPress site<\/a><\/h3>\n\n\n\n<p>Well, you can protect something that doesn&#8217;t exist. Therefore, you need to be having a WordPress site up and running. You can follow the link below to learn how to install and setup WordPress site with Nginx and MySQL 8 on CentOS 8 system.<\/p>\n\n\n\n<p><a href=\"https:\/\/kifarunix.com\/install-wordpress-with-nginx-and-mysql-8-on-centos-8\/\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">Install WordPress with Nginx and MySQL 8 on CentOS 8<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"install-and-setup-lib-mod-security-on-cent-os-8\"><a href=\"#install-modsecurity-centos-8\">Install and Setup LibModSecurity on CentOS 8<\/a><\/h3>\n\n\n\n<p>In our demo, we have our WordPress running on a CentOS 8. We have also covered how to install and setup LibModSecurity with Apache or Nginx web server in our previous tutorials. Depending on the type of web server your site is hosted on, follow any of the links below to install WordPress.<\/p>\n\n\n\n<p><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/kifarunix.com\/configure-libmodsecurity-with-apache-on-centos-8\/\" target=\"_blank\" rel=\"noreferrer noopener\">Configure LibModsecurity with Apache on CentOS 8<\/a><\/p>\n\n\n\n<p><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/kifarunix.com\/configure-libmodsecurity-with-nginx-on-centos-8\/\" target=\"_blank\" rel=\"noreferrer noopener\">Configure LibModsecurity with Nginx on CentOS 8<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"restrict-access-to-word-press-login-page-to-specific-i-ps\"><a href=\"#restrict-wp-login-access-with-libmodsecurity\">Restrict Access to WordPress Login Page to Specific IPs<\/a><\/h3>\n\n\n\n<p>Now that you have ModSecurity WAF in place, let us proceed configure it to restrict access to WordPress login page from specific IP addresses.<\/p>\n\n\n\n<p>We have already installed the OWASP ModSecurity Core Rule Set (CRS) while setting up ModSecurity, which provides a set of generic attack detection rules.<\/p>\n\n\n\n<p>We specified the location of these rules in our ModSecurity rules file, <code>\/etc\/httpd\/conf.d\/modsecurity.d\/rules.conf<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>less \/etc\/httpd\/conf.d\/modsecurity.d\/rules.conf<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/modsecurity.conf\"\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/owasp-crs\/crs-setup.conf\"\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/owasp-crs\/rules\/*.conf\"\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"create-custom-rules-to-restrict-access-to-word-press-login-page\"><a href=\"#custom-rules-to-restrict-wp-login.php-access\">Create Custom Rules to Restrict Access to WordPress Login Page<\/a><\/h4>\n\n\n\n<p>Create a custom rules configuration file;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>vim \/etc\/httpd\/conf.d\/modsecurity.d\/custom.conf<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"create-a-rule-to-allow-access-to-word-press-login-page-uri-wp-login-php-from-specific-ip-addresses\">Create a Rule to Allow Access to WordPress login page, (URI, wp-login.php) from Specific IP addresses.<\/h4>\n\n\n\n<p>See below;<\/p>\n\n\n\n<p>ModSecurity rules are defined using the <strong><code>SecRule<\/code><\/strong> directive. SecRule is made up of 4 parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Variables<\/strong> &#8211; Instructs ModSecurity&nbsp;where&nbsp;to look (sometimes called Targets).<\/li>\n\n\n\n<li><strong>Operators<\/strong> &#8211; Instructs ModSecurity&nbsp;<em>when<\/em>&nbsp;to trigger a match.<\/li>\n\n\n\n<li><strong>Transformations<\/strong> &#8211; Instructs ModSecurity&nbsp;<em>how<\/em>&nbsp;it should normalize variable data .<\/li>\n\n\n\n<li><strong>Actions<\/strong> &#8211; Instructs ModSecurity&nbsp;<em>what<\/em>&nbsp;to do if a rule matches<\/li>\n<\/ul>\n\n\n\n<p>The Syntax of the rule is;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>SecRule VARIABLES \"OPERATOR\" \"TRANSFORMATIONS,ACTIONS\"<\/code><\/pre>\n\n\n\n<p>Read more about this on <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/www.modsecurity.org\/CRS\/Documentation\/making.html\" target=\"_blank\" rel=\"noreferrer noopener\">Making ModSecurity rules<\/a>.<\/p>\n\n\n\n<p>For the configuration directives, check <a href=\"https:\/\/github.com\/SpiderLabs\/ModSecurity\/wiki\/Reference-Manual-%28v2.x%29#configuration-directives\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">Reference Manual<\/a>.<\/p>\n\n\n\n<p>Therefore, our rule looks like;<\/p>\n\n\n\n<pre class=\"scroll-box\"><code>\nSecRule REQUEST_URI \"@eq \/wp-login.php\" \\\n  \"chain, \\\n  id:'2000', \\\n  phase:1, \\\n  log, \\\n  pass\"\n  SecRule REMOTE_ADDR \"@ipMatch 192.168.57.1,192.168.57.21\" \\\n    ctl:ruleEngine=DetectionOnly\n<\/code><\/pre>\n\n\n\n<p>Dissecting the rule into parts;<\/p>\n\n\n\n<p>The <strong><a href=\"https:\/\/github.com\/SpiderLabs\/ModSecurity\/wiki\/Reference-Manual-%28v2.x%29#variables\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">VARIABLES<\/a><\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>REQUEST_URI<\/strong>: This variable holds the full request URL including the query string dataREQUEST_URI without the domain part. For example, the <code>\/wp-login.php<\/code>.<\/li>\n\n\n\n<li><strong>REMOTE_ADDR<\/strong>: This variable holds the IP address of the remote client. If Apache directive HostnameLookups is set to On, then you can use <strong>REMOTE_HOST<\/strong> variable which holds the remote hostname resolved through DNS.<\/li>\n<\/ul>\n\n\n\n<p>The <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/github.com\/SpiderLabs\/ModSecurity\/wiki\/Reference-Manual-%28v2.x%29#operators\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>OPERATORS<\/strong><\/a>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>@eq<\/strong>: Performs numerical comparison and returns true if the input value is equal to the provided parameter<\/li>\n\n\n\n<li><strong>@ipMatch<\/strong>: Performs a fast ipv4 or ipv6 match of REMOTE_ADDR variable data. Multiple addresses can be separated with commas.<\/li>\n<\/ul>\n\n\n\n<p>The <strong><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/github.com\/SpiderLabs\/ModSecurity\/wiki\/Reference-Manual-%28v2.x%29#Actions\" target=\"_blank\" rel=\"noreferrer noopener\">ACTIONS<\/a><\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>chain<\/strong>: Chains the current rule with the rule that immediately follows it, creating a rule chain. <em>Rule chains allow you to simulate <strong>logical AND<\/strong>. The disruptive actions specified in the first portion of the chained rule will be triggered only if all of the variable checks return positive hits.<\/em><\/li>\n\n\n\n<li><strong>id<\/strong>: Assigns a unique ID to the rule or chain in which it appears. The value must be numeric. 1\u201399,999: reserved for local (internal) use.&nbsp;<\/li>\n\n\n\n<li><strong>phase<\/strong>: Places the rule or chain into one of five available processing phases.\n<ul class=\"wp-block-list\">\n<li><strong>Request headers (phase 1)<\/strong>: Analyzes the request headers first.<\/li>\n\n\n\n<li><strong>Request body (phase 2)<\/strong>: The request body phase is the main request analysis phase and takes place immediately after a complete request body has been received and processed.<\/li>\n\n\n\n<li><strong>Response headers (phase 3)<\/strong>: The response headers phase takes place after response headers become available, but before a response body is read.<\/li>\n\n\n\n<li><strong>Response body (phase 4)<\/strong>: The main response analysis phase.<\/li>\n\n\n\n<li><strong>Logging (phase 5)<\/strong>: The only phase you can&#8217;t block.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>log<\/strong>: Indicates that a successful match of the rule needs to be logged.<\/li>\n\n\n\n<li><strong>pass<\/strong>: Continues processing with the next rule in spite of a successful match.<\/li>\n\n\n\n<li><strong><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/github.com\/SpiderLabs\/ModSecurity\/wiki\/Reference-Manual-%28v2.x%29#ctl\" target=\"_blank\" rel=\"noreferrer noopener\">ctl<\/a><\/strong>: Changes ModSecurity configuration on transient, per-transaction basis. Any changes made using this action will affect only the transaction in which the action is executed. ruleEngine=DetectionOnly, changes the Operating mode for ModSecurity for this specific rule.<\/li>\n<\/ul>\n\n\n\n<p>So basically the rule takes each HTTP request and extract the URI portion equalling to <code>wp-login.php<\/code>, it assigns the rule a unique ID of 2001, places the rule on request header phase, logs the rule in-case of a successful match, chains the rule with the next one, continues to process the next rule which checks if the request IP address matches the specified ones, and if true, put ModSecurity in detection only, permissive, mode.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"create-a-rule-to-deny-any-access-to-word-press-login-page\">Create a Rule to Deny Any Access to WordPress login page<\/h4>\n\n\n\n<p>Next, you need to block all other access to WordPress login page. Hence, create a rule that denies access. Place the rule in the same file above, just after the above rule;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>SecRule REQUEST_URI \"@contains wp-login\" \"id:2001,phase:1,t:lowercase,log,deny,msg:'Warning, Access to WordPress Login page is Restricted'\"<\/code><\/pre>\n\n\n\n<p>Our general rule now looks like;<\/p>\n\n\n\n<pre class=\"scroll-box\"><code>\nSecRule REQUEST_URI \"@eq \/wp-login.php\" \\\n  \"chain, \\\n  id:'2000', \\\n  phase:1, \\\n  log, \\\n  pass\"\n  SecRule REMOTE_ADDR \"@ipMatch 192.168.57.1,192.168.57.21\" \\\n    ctl:ruleEngine=DetectionOnly\nSecRule REQUEST_URI \"@contains wp-login\" \"id:2001,phase:1,t:lowercase,log,deny,msg:'Warning, Access to WordPress Login page is Restricted'\"\n<\/code><\/pre>\n\n\n\n<p>Note that you can even use regular expressions;<\/p>\n\n\n\n<pre class=\"scroll-box\"><code>\nSecRule REQUEST_URI \"@rx \/wp-(login\\.php|admin)\" \\\n  \"chain, \\\n  id:2000, \\\n  phase:1, \\\n  log, \\\n  pass\"\n  SecRule REMOTE_ADDR \"@ipMatch 192.168.57.1,192.168.57.21\" \\\n    ctl:ruleEngine=DetectionOnly\nSecRule REQUEST_URI \"@rx \/wp-(login\\.php|admin)\" \"id:2001,phase:1,t:lowercase,log,deny,status:403\"\n<\/code><\/pre>\n\n\n\n<p>Read more about rules <a href=\"https:\/\/github.com\/SpiderLabs\/ModSecurity\/wiki\/Reference-Manual-(v2.x)-Operators\" target=\"_blank\" rel=\"noreferrer noopener\">operators<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"configure-mod-security-to-process-custom-rules\">Configure ModSecurity to Process Custom Rules<\/h3>\n\n\n\n<p>Now that we have the rule ready, configure ModSecurity to process this rule.<\/p>\n\n\n\n<p>In our setup, <code><strong>\/etc\/httpd\/conf.d\/modsecurity.d\/rules.conf<\/strong><\/code> is our main ModSecurity rules configuration file.<\/p>\n\n\n\n<p>Hence, we need to include our custom rule configuration file, in the main rules file.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>echo 'Include \"\/etc\/httpd\/conf.d\/modsecurity.d\/custom.conf\"' &gt;&gt; \/etc\/httpd\/conf.d\/modsecurity.d\/rules.conf<\/code><\/pre>\n\n\n\n<p>Our main rules configuration file looks like in below now;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>less \/etc\/httpd\/conf.d\/modsecurity.d\/rules.conf<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/modsecurity.conf\"\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/owasp-crs\/crs-setup.conf\"\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/owasp-crs\/rules\/*.conf\"\nInclude \"\/etc\/httpd\/conf.d\/modsecurity.d\/custom.conf\"\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"restart-apache\">Restart Apache<\/h3>\n\n\n\n<p>To effect the changes, restart Apache;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>systemctl restart httpd<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"testing-access-to-word-press-login\">Testing Access to WordPress Login<\/h3>\n\n\n\n<p>To verify if our rule works, simply try to access WordPress from a source, whose IP address is not part of the whitelisted addresses above.<\/p>\n\n\n\n<p>In our case, we are testing this from a system whose IP address is, <code><strong>192.168.57.22<\/strong><\/code>.<\/p>\n\n\n\n<p>If all is well, on the browser, you will get such an error;<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1281\" height=\"373\" src=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/07\/block-word-press-login-modsecurity.png\" alt=\"Restrict Access to WordPress Login Page to Specific IPs with libModSecurity\" class=\"wp-image-6361\" title=\"\" srcset=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/07\/block-word-press-login-modsecurity.png?v=1594472073 1281w, https:\/\/kifarunix.com\/wp-content\/uploads\/2020\/07\/block-word-press-login-modsecurity-768x224.png?v=1594472073 768w\" sizes=\"(max-width: 1281px) 100vw, 1281px\" \/><\/figure>\n\n\n\n<p>On the logs, you should see such a log entry;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>tail -f \/var\/log\/httpd\/modsec_audit.log<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\n...\n---pnERTMML---A--\n[11\/Jul\/2020:15:33:58 +0300] 159447083849.637890 <strong>192.168.57.22<\/strong> 48084 wp.kifarunix-demo.com 0\n---pnERTMML---B--\nGET \/wp-login.php?redirect_to=http%3A%2F%2Fwp.kifarunix-demo.com%2Fwp-admin%2F&amp;reauth=1 HTTP\/1.1\nHost: wp.kifarunix-demo.com\nUser-Agent: Mozilla\/5.0 (X11; Linux x86_64; rv:60.0) Gecko\/20100101 Firefox\/60.0\nCookie: wordpress_test_cookie=WP+Cookie+check\nAccept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate\nConnection: keep-alive\nUpgrade-Insecure-Requests: 1\n\n---pnERTMML---D--\n\n---pnERTMML---F--\nHTTP\/1.1 403\n\n---pnERTMML---H--\n<strong>ModSecurity: Access denied with code 403 (phase 1). Matched \"Operator `Contains' with parameter `wp-login' against variable `REQUEST_URI' (Value: `\/wp-login.php?redirect_to=http:\/\/wp.kifarunix-demo.com\/wp-admin\/&amp;reauth=1' ) [file \"\/etc\/httpd\/conf.d\/modsecurity.d\/custom.conf\"] [line \"8\"] [id \"2001\"] [rev \"\"] [msg \"Warning, Access to WordPress Login page is Restricted\"] [data \"\"] [severity \"0\"] [ver \"\"] [maturity \"0\"] [accuracy \"0\"] [hostname \"wp.kifarunix-demo.com\"] [uri \"\/wp-login.php\"] [unique_id \"159447083849.637890\"] [ref \"o1,8v4,83t:lowercase\"]<\/strong>\n...\n<\/code><\/pre>\n\n\n\n<p>There are other many ways of protecting WordPress against attacks. Thus blocking access to wp-login.php page helps curb the bruteforce attacks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"related-tutorials\">Related Tutorials<\/h3>\n\n\n\n<p><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/kifarunix.com\/install-libmodsecurity-with-apache-on-ubuntu-18-04\/\" target=\"_blank\" rel=\"noreferrer noopener\">Install LibModsecurity with Apache on Ubuntu 18.04<\/a><\/p>\n\n\n\n<p><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/kifarunix.com\/install-libmodsecurity-with-apache-on-fedora-30-29-centos-7\/\" target=\"_blank\" rel=\"noreferrer noopener\">Install LibModsecurity with Apache on Fedora 30\/29\/CentOS 7<\/a><\/p>\n\n\n\n<p><a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/kifarunix.com\/how-to-perform-system-security-auditing-with-lynis-on-ubuntu-18-04\/\" target=\"_blank\" rel=\"noreferrer noopener\">How to Perform System Security Auditing with Lynis on Ubuntu 18.04<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/kifarunix.com\/setup-ipsec-vpn-server-with-libreswan-on-centos-8\/\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">Setup IPSec VPN Server with Libreswan on CentOS 8<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we are going to learn how to restrict access to WordPress login page to specific IPs with libModSecurity. libModSecurity&nbsp;is also known as<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_lock_modified_date":false,"footnotes":""},"categories":[34,121,1207],"tags":[202,1763,1140,1139,1762,1764,1047],"class_list":["post-6360","post","type-post","status-publish","format-standard","hentry","category-security","category-howtos","category-modsecurity","tag-apache","tag-block-wp-login-with-modsecurity","tag-libmodsecurity","tag-modsecurity","tag-protect-wordpress-with-modsecurity","tag-restrict-wordpress-wp-login-php-to-specific-ips","tag-wordpress","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50"],"_links":{"self":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/6360"}],"collection":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/comments?post=6360"}],"version-history":[{"count":11,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/6360\/revisions"}],"predecessor-version":[{"id":21452,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/6360\/revisions\/21452"}],"wp:attachment":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/media?parent=6360"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/categories?post=6360"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/tags?post=6360"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}