Login

How to Protect Your Plesk Login from Brute Force Attacks on Windows Server

Is your Plesk control panel running slower than usual? If so, you might be experiencing a brute force attack—a widespread issue affecting nearly all Plesk installations since mid-March 2025. Fortunately, we’ve developed an effective solution using Cloudflare to stop these attacks in their tracks. Follow the step-by-step guide below to secure your server.

Step 1: Confirm You’re Under Attack

To determine if your Plesk instance is being targeted, log in as an admin. From the left menu, navigate to Extensions, then search for and install the free Log Browser extension.

plesk extensions
Accessing extensions in Plesk

Once installed, open the Log Browser. If you’re under attack, you’ll notice a flood of failed login attempts, updated within seconds and continuously increasing, as shown below:

screen shot from plesk log browser
Example of brute force attack logs

Step 2: Secure Plesk with Cloudflare

To stop the attacks, we’ll configure Plesk to load exclusively through a single, secure URL protected by Cloudflare. For this guide, we’ll use plesk-1.ourdomain.com as the example subdomain.

Configure DNS
In Cloudflare’s DNS manager, add your Plesk subdomain (e.g., plesk-1.ourdomain.com) and enable Cloudflare protection. An orange cloud icon indicates it’s active, as shown below:

Set Up Cloudflare
Create an account at Cloudflare.com, log in, and add the domain hosting your Plesk subdomains (e.g., ourdomain.com). Update your domain’s nameservers to Cloudflare’s as instructed.

screenshot of cloudflare dns records
DNS setup with Cloudflare protection enabled

Create Page Rules
From the left menu, go to Rules > Page Rules, then click Create Rule. Set up the following three rules:

Save the rule.

Rule 1: Enable “I’m Under Attack” Mode

URL: plesk-*.ourdomain.com (or *.ourdomain.com for all subdomains)

Setting: Security Level > I’m Under Attack

image
Activating attack protection

Rule 2: Bypass Cache

URL: Same as above

Setting: Cache Level > Bypass

Save the rule.

image
Ensuring cache doesn’t interfere

Rule 3: Enforce HTTPS

Save the rule.

URL: Same as above

Setting: Automatic HTTPS Rewrites > On

image
Forcing secure connections

Test the Setup
Visit your Plesk URL (e.g., https://plesk-1.ourdomain.com:8443). You should see a Cloudflare bot verification screen before being redirected to the login page:

cloudflare protected web page screenshot
Cloudflare verifying traffic

Step 3: Server-Side Configuration

Next, we’ll route all Plesk traffic to your secure URL and ensure the rule persists after updates.

RDP to Your Server
Log in to your Plesk server via Remote Desktop and open a text editor (e.g., Notepad or Notepad++).

Add a PowerShell Script
Save the following script as c:\Plesk_ssl_redirect.ps1 (or your preferred location):

Import-Module WebAdministration

$siteName = "pleskcontrolpanel"
$ruleName = "Redirect to our secure domain"
$redirectUrl = "https://plesk-1.ourdomain.com:8443/{R:0}"

# Get the physical path of the site
$site = Get-Website -Name $siteName
if (-not $site) {
    Write-Error "Site '$siteName' not found in IIS."
    exit 1
}
$physicalPath = $site.physicalPath
$webConfigPath = Join-Path $physicalPath "web.config"

# If web.config doesn't exist, create a basic configuration file.
if (-not (Test-Path $webConfigPath)) {
    $xmlContent = @"
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>
"@
    $xmlContent | Out-File -Encoding UTF8 $webConfigPath
}

# Load the web.config as XML.
[xml]$webConfig = Get-Content $webConfigPath

# Ensure <system.webServer> node exists.
if (-not $webConfig.configuration.'system.webServer') {
    $systemWebServerNode = $webConfig.CreateElement("system.webServer")
    $webConfig.configuration.AppendChild($systemWebServerNode) | Out-Null
}
$systemWebServer = $webConfig.configuration.'system.webServer'

# Ensure the <rewrite> node exists.
if (-not $systemWebServer.rewrite) {
    $rewriteNode = $webConfig.CreateElement("rewrite")
    $systemWebServer.AppendChild($rewriteNode) | Out-Null
}
$rewrite = $systemWebServer.rewrite

# Ensure the <rules> node exists.
if (-not $rewrite.rules) {
    $rulesNode = $webConfig.CreateElement("rules")
    $rewrite.AppendChild($rulesNode) | Out-Null
}
$rules = $rewrite.rules

# Check if the rule already exists.
$existingRule = $rules.rule | Where-Object { $_.name -eq $ruleName }

if ($existingRule) {
    Write-Output "Rule '$ruleName' already exists in '$siteName'. No action taken."
} else {
    Write-Output "Rule '$ruleName' not found. Creating it now."

    # Create the <rule> element.
    $rule = $webConfig.CreateElement("rule")
    $rule.SetAttribute("name", $ruleName)
    $rule.SetAttribute("enabled", "true")
    $rule.SetAttribute("stopProcessing", "true")

    # Create and append the <match> element.
    $match = $webConfig.CreateElement("match")
    $match.SetAttribute("url", "(.*)")
    $match.SetAttribute("ignoreCase", "true")
    $rule.AppendChild($match) | Out-Null

    # Create and append the <conditions> element.
    $conditions = $webConfig.CreateElement("conditions")
    $conditions.SetAttribute("logicalGrouping", "MatchAll")
    $conditions.SetAttribute("trackAllCaptures", "false")

    $condition = $webConfig.CreateElement("add")
    $condition.SetAttribute("input", "{HTTP_HOST}")
    $condition.SetAttribute("pattern", "^plesk-1\.ourdomain\.com(:8443)?$")
    $condition.SetAttribute("negate", "true")
    $conditions.AppendChild($condition) | Out-Null
    $rule.AppendChild($conditions) | Out-Null

    # Create and append the <action> element.
    $action = $webConfig.CreateElement("action")
    $action.SetAttribute("type", "Redirect")
    $action.SetAttribute("url", $redirectUrl)
    $action.SetAttribute("redirectType", "Permanent")
    $rule.AppendChild($action) | Out-Null

    # Append the new rule to the <rules> node.
    $rules.AppendChild($rule) | Out-Null

    # Save the updated web.config.
    $webConfig.Save($webConfigPath)

    Write-Output "Rule '$ruleName' created successfully."
}

Update lines 5 and 83 with your secure subdomain (e.g., plesk-1.ourdomain.com). This script checks the Plesk URL and redirects traffic to your secure subdomain if it doesn’t match.

Schedule the Script

Open Task Scheduler from the Start menu.

Right-click Task Scheduler Library and select Create Basic Task. Name it (e.g., “Plesk SSL Redirection”).

Set it to Daily, recurring every 1 day.

Choose Start a Program:

Program: powershell.exe

Arguments: -ExecutionPolicy Bypass -File "C:\Plesk_ssl_redirect.ps1"

image
Configuring the scheduled task

After creating, check Open the Properties dialog and click Finish.

image
task scheduler on windows server

In the General tab, select Run whether user is logged on or not.

image
Setting run permissions

In the Triggers tab, edit the daily trigger to repeat every 1 hour indefinitely. This ensures the rule is reapplied if a Plesk update removes it.

image
Hourly rule enforcement

Save changes by clicking OK on both screens followed by entering your RDP credentials when prompted.

Run the Task

Locate your task in the list, right-click, and select Run.

Test by visiting http://PLESK_SERVER_IP:8880—it should redirect to https://plesk-1.ourdomain.com:8443.

Verify the Attack Stopped

Log in to Plesk as admin, open the Log Browser, and confirm the failed login attempts have ceased.

Step 4: Final Plesk Adjustments

A few additional tweaks will ensure smooth operation:

Set the Custom Plesk URL
Go to Tools & Settings > Customizing Plesk URL, select the middle option, enter your subdomain (e.g., plesk-1.ourdomain.com), and save.

image
Updating Plesk’s default URL

Allow IP Changes

Navigate to Tools & Settings > Session Idle Time, enable Allow IP address changes during a single session, and click OK. This accommodates Cloudflare’s multiple IPs.

image
Preventing session timeouts

Check Task Manager

Visit Tools & Settings > Task Manager. If it loads, you’re set. If it times out or shows a PHP error due to the attack’s impact, proceed to the next step.

Step 5: Repair Task Manager (If Needed)

If Task Manager fails to load:

Stop the Service
Open the Plesk Service Monitor from the system tray on your Plesk Server, check Plesk Task Manager Service, and click Stop.

image
Stopping the task manager service

Clear the Database
Navigate to C:\Program Files (x86)\Plesk\var\task-manager\db\, then delete or move db.sqlite3 and any other files in the folder.

Remove Pending Tasks
Open PowerShell and run:

Get-ChildItem "C:\Program Files (x86)\Plesk\var\task-manager\runtime" -Recurse |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddMinutes(-5) } |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue

This clears queued login attempts that may have crashed the service.

Restart the Service
In the Plesk Service Monitor, Start the Plesk Task Manager Service. Reload the Task Manager page in Plesk—it should now work.

If this guide helped you secure your Plesk server, please leave a comment below!

avatar of chris danks

About Chris Danks

Chris Danks has written 88 post in this blog.

Need Help?
Contact our friendly team

Our highly skilled technical support agents are available to answer your questions 7 days a week through live chat and support ticket with a typical response time is under 1 hour. Having issues with your website or just need some advice? Contact us today and we'll be happy to help!

The Hosting Heroes - Join Up With Our Affiliate Programme!