How to set IIS restrictions prevent WordPress be hacked by login and xmlrpc.php

1 QUICK START (Must Read)
wp-admin/wp-login.php and xmlrpc.php are frequently targeted by bots in brute force attacks.  Even if the site is secured to prevent the brute force attacks from succeeding, a common result of the repeated requests is the site will see a CPU spike causing it to become much slower to respond or it will error out with a "500.0 The FastCGI process exited unexpectedly".  Within IIS, restricting access can be accomplished via the ipSecurity element.  Implemented by updating the WordPress web.config file.  With a complete example web.config found at the bottom of this article.
 
Note that these updates only prevent access to files after a request has already reached the server.  To monitor and stop the requests themselves, a service like Cloudflare should also be considered.
 
 
wp-login.php and /wpadmin
 
First, obtain the IP address of any user that needs to have access to the admin section of WordPress.  When not known, simply Google "my IP".  From there add two new sections to the configuration element of the web.config as in the example below
 
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <location path="wp-login.php">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
          <add ipAddress="xx.xx.xx.xx" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>

  <location path="wp-admin">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
          <add ipAddress="xx.xx.xx.xx" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>
 
Replacing the ""xx.xx.xx.xx" with the IP address of the user.  If there is more than one user, simply copy and paste as many "add ipAddress" lines as necessary below those in the example.
 
 
xmlrpc.php
 
xmlrpc.php is a WordPress API that is being phased out, but most notably is still used for WordPress' own JetPack plugin.  The same general syntax can be used to deny access to xmlrpc.php.  However, if using JetPack, then it's necessary to allow WordPress IP ranges found at https://jetpack.com/support/hosting-faq/#jetpack-whitelist
 
When not using a plugin like JetPack that requires whitelisting, add a new web.config section like the example below
 
  <location path="xmlrpc.php">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
        </ipSecurity>
      </security>
    </system.webServer>
  </location>
 
Because JetPack requires an IP range to be whitelisted, rather than a single IP address, the additional syntax is required in the form of "subnetMask".  To get a subnet mask from a CIDR like those provided by JetPack, a converter like https://www.ipaddressguide.com/cidr may be used.
 
Using 122.248.245.244/32 as an example, the syntax for adding the IP address and subnet mask is
 
<add ipAddress="122.248.245.244" subnetMask="255.255.255.255" allowed="true" />
 
Then an example of the full section being
 
  <location path="xmlrpc.php">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
          <add ipAddress="122.248.245.244" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="54.217.201.243" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="54.232.116.4" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="192.0.80.0" subnetMask="255.255.240.0" allowed="true" />
          <add ipAddress="192.0.96.0" subnetMask="255.255.240.0" allowed="true" />
          <add ipAddress="192.0.112.0" subnetMask="255.255.240.0" allowed="true" />
          <add ipAddress="195.234.108.0" subnetMask="255.255.252.0" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>
 
 
Example WordPress web.config with Permalinks
 
An example of a full WordPress web.config with the above restrictions, JetPack whitelisted IPs and WordPress permalinks rewrite rule
                    
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <location path="wp-login.php">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
          <add ipAddress="xx.xx.xx.xx" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>

  <location path="wp-admin">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
          <add ipAddress="xx.xx.xx.xx" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>
  
  <location path="xmlrpc.php">
    <system.webServer>
      <security>
        <ipSecurity allowUnlisted="false">
          <add ipAddress="122.248.245.244" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="54.217.201.243" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="54.232.116.4" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="192.0.80.0" subnetMask="255.255.240.0" allowed="true" />
          <add ipAddress="192.0.96.0" subnetMask="255.255.240.0" allowed="true" />
          <add ipAddress="192.0.112.0" subnetMask="255.255.240.0" allowed="true" />
          <add ipAddress="195.234.108.0" subnetMask="255.255.252.0" allowed="true" />
          <add ipAddress="192.0.96.202" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="192.0.98.138" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="192.0.102.71" subnetMask="255.255.255.255" allowed="true" />
          <add ipAddress="192.0.102.95" subnetMask="255.255.255.255" allowed="true" />
        </ipSecurity>
      </security>
    </system.webServer>
  </location>

  <system.webServer>
    <rewrite>
      <rules>
        <rule name="WordPress Rule" stopProcessing="true">
          <match url=".*" />
            <conditions>
              <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
              <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            </conditions>
          <action type="Rewrite" url="index.php" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>