By default, only members of the Domain Admins group have the remote RDP access to the Active Directory domain controllers‘ desktop. In this article we’ll show how to grant RDP access to domain controllers for non-admin user accounts without granting administrative privileges.
Many of you can quite reasonably ask: why would ordinary domain users should have access to the DC desktop? Indeed, in small or middle size infrastructures, when several administrators with the privileges of domain admins maintain them, you’ll hardly need this. In most cases, delegating some administrative permissions in Active Directory or using PowerShell Just Enough Administration (JEA) is sufficient.
However, in large corporate networks maintained by many administrators, it may become necessary to grant RDP access to the DC (usually to branch office DC’s or RODC) for different server admin groups, monitoring team, on-duty administrators, or other technical staffs. Also, from time to time some of the third-party services, not managed by the domain administrators, are deployed on the DC, and there’s a need to maintain these services.
Tip. Microsoft doesn’t recommend to install the Active Directory Domain Services and Remote Desktop Service role (terminal server) on a single server. If there is only one physical server, on which you want to deploy both DC and RDS, you’d better use virtualization, since Microsoft virtualization licensing policy allows you to run two virtual servers under the same Windows Server Standard license.
To Sign in Remotely, You Need the Rights to Sign in through Remote Desktop Services
After the server has been promoted to the domain controller, you cannot manage local users and groups from the Computer Management mmc snap-in. When you try to open Local Users and Groups (lusrmgr.msc) console, the following error appears:
The computer xxx is a domain controller. This snip-in cannot be used on a domain controller. Domain accounts are managed with the Active Directory Users and Computers snap-in.
As you can see, there are no local groups on the domain controller. Instead of the local group Remote Desktop Users, the DC uses the built-in domain group Remote Desktop Users (located in the Builtin container). You can manage this group from the ADUC console or from the command prompt on the DC.
Display the members of the domain group Remote Desktop Users on the domain controller using the command:
net localgroup "Remote Desktop Users"
As you can see, it is empty. Add a domain user it-pro to it (in our example, it-pro is a regular domain user without administrative privileges):
net localgroup "Remote Desktop Users" /add corp\it-pro
Make sure that the user is added to this group:
net localgroup "Remote Desktop Users"
You can also verify that the user is now a member of the Remote Desktop Users domain group using the ADUC (dsa.msc) snap-in.
However, even after that, a user still cannot connect to the DC via Remote Desktop with the error:
To sign in remotely, you need the right to sign in through Remote Desktop Services. By default members of the Administrators group have this right. If the group you’re in does not have the right, or if the right has been removed from the Administrators group, you need to be granted the right manually.
Group Policy: Allow Log on through Remote Desktop Services
To allow a domain user or group a remote RDP connection to Windows, you must grant it the SeRemoteInteractiveLogonRight privileges. By default, only members of the Administrators group have this right. You can grant this permission using the Allow log on through Remote Desktop Services policy.
In Windows 2003 and older this policy is called Allow log on through terminal services.
To allow remote connection to the domain controllers for members of the Remote Desktop Users group you need to change the settings of this policy on your domain controller:
Launch the Local Group Policy Editor (gpedit.msc);
Go to the GPO section Computer Configuration -> Windows settings -> Security Settings -> Local policies -> User Rights Assignment;
Find the policy Allow log on through Remote Desktop Services;After the server is promoted to the DC, only the Administrators group (these are Domain Admins) remains in this local policy.
Edit the policy, add the domain group Remote Desktop Users (like this: domainname\Remote Desktop Users), or directly the domain user, or a group (domain\CA_Server_Admins) to it;
Note that the group that you added to the Allow log on through Remote Desktop Services policy should not be present in the “Deny log on through Remote Desktop Services” policy , because it has a higher priority (check the article Restricting Network Access under local accounts). In addition, if you are restricting the list of computers on which users can log on, you need to add the DC name to the properties of the AD account (LogonWorkstations user attribute).
Note. To allow a user to log on to the DC locally (via the server console), you must add the account or group to the policy “Allow log on locally”. By default, this permission is allowed for the following domain groups:
Backup Operators
Administrators
Print Operators
Server Operators
Account Operators
It is better to create a new security group in the domain, for example, AllowLogonDC and add user accounts to it that need remote access to the DC. If you want to allow access to all AD domain controllers at once, instead of editing of the Local Policy on each DC, it’s better to add a the user group to the Default Domain Controllers Policy using the GPMC.msc console (change the policy settings in the same section: Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment -> Allow log on through Remote Desktop Services).
Warning. If you change the Default Domain Controllers Policy, don’t forget to add the domain/enterprise administrator groups to the policy Allow log on through Remote Desktop Services, otherwise they will lose remote access to the DCs.
Now the users (groups) you added to the policy will be able to connect to the AD domain controllers via RDP.
If you need to grant non-administrator users the permissions to start/stop certain services on a DC, use the following guide.
The Requested RDP Session Access is Denied
In some cases, when connecting via RDP to a domain controller, an error may appear:
The requested session access is denied.
If you are connecting to the DC under a non-admin user account, this could be due to two problems:
You are trying to connect to the server console (using the mstsc /admin mode). This connection mode is only allowed for administrators. Try to connect to the server using mstsc.exe client in normal RDP mode (without /admin option);
The server may already have two active RDP sessions (by default, you can’t use more than two simultaneously RDP sessions on Windows Server without RDS role). You cannot log off other users without administrator permissions. You need to wait for the administrators to release one of the sessions.
If you haven’t patched CVE-2022-22954 yet, now would be an excellent time to do so.
Hackers have been exploiting a now-patched vulnerability in VMware Workspace ONE Access in campaigns to install various ransomware and cryptocurrency miners, a researcher at security firm Fortinet said on Thursday.
FURTHER READING
2 vulnerabilities with 9.8 severity ratings are under exploit. A 3rd loomsCVE-2022-22954 is a remote code execution vulnerability in VMware Workspace ONE Access that carries a severity rating of 9.8 out of a possible 10. VMware disclosed and patched the vulnerability on April 6. Within 48 hours, hackers reverse-engineered the update and developed a working exploit that they then used to compromise servers that had yet to install the fix. VMware Workspace ONE access helps administrators configure a suite of apps employees need in their work environments.
In August, researchers at Fortiguard Labs saw a sudden spike in exploit attempts and a major shift in tactics. Whereas before the hackers installed payloads that harvested passwords and collected other data, the new surge brought something else—specifically, ransomware known as RAR1ransom, a cryptocurrency miner known as GuardMiner, and Mirai, software that corrals Linux devices into a massive botnet for use in distributed denial-of-service attacks.
“Although the critical vulnerability CVE-2022-22954 is already patched in April, there are still multiple malware campaigns trying to exploit it,” Fortiguard Labs researcher Cara Lin wrote. Attackers, she added, were using it to inject a payload and achieve remote code execution on servers running the product.
The Mirai sample Lin saw getting installed was downloaded from http[:]//107[.]189[.]8[.]21/pedalcheta/cutie[.]x86_64 and relied on a command and control server at “cnc[.]goodpackets[.]cc. Besides delivering junk traffic used in DDoSes, the sample also attempted to infect other devices by guessing the administrative password they used. After decoding strings in the code, Lin found the following list of credentials the malware used:
hikvision
1234
win1dows
S2fGqNFs
root
tsgoingon
newsheen
12345
default
solokey
neworange88888888
guest
bin
user
neworang
system
059AnkJ
telnetadmin
tlJwpbo6
iwkb
141388
123456
20150602
00000000
adaptec
20080826
vstarcam2015
v2mprt
Administrator
1001chin
vhd1206
support
NULL
xc3511
QwestM0dem
7ujMko0admin
bbsd-client
vizxv
fidel123
dvr2580222
par0t
hg2x0
samsung
t0talc0ntr0l4!
cablecom
hunt5759
epicrouter
zlxx
pointofsale
nflection
admin@mimifi
xmhdipc
icatch99
password
daemon
netopia
3com
DOCSIS_APP
hagpolm1
klv123
OxhlwSG8
In what appears to be a separate campaign, attackers also exploited CVE-2022-22954 to download a payload from 67[.]205[.]145[.]142. The payload included seven files:
phpupdate.exe: Xmrig Monero mining software
config.json: Configuration file for mining pools
networkmanager.exe: Executable used to scan and spread infection
phpguard.exe: Executable used for guardian Xmrig miner to keep running
init.ps1: Script file itself to sustain persistence via creating scheduled task
clean.bat: Script file to remove other cryptominers on the compromised host
encrypt.exe: RAR1 ransomware
In the event RAR1ransom has never been installed before, the payload would first run the encrypt.exe executable file. The file drops the legitimate WinRAR data compression executable in a temporary Windows folder. The ransomware then uses WinRAR to compress user data into password-protected files.
The payload would then start the GuardMiner attack. GuardMiner is a cross-platform mining Trojan for the Monero currency. It has been active since 2020.
The attacks underscore the importance of installing security updates in a timely manner. Anyone who has yet to install VMware’s April 6 patch should do so at once.
[German]As of October 17, 2022, Microsoft has released several unscheduled updates for Windows. These updates fix a connection problem that can occur with SSL and TLS connections. Affected by this problem are probably all Windows client and server. Below I have listed all available updates and also give some hints where problems occur without these updates.
Advertising
Out-of-band updates with TLS fix
Microsoft made a mistake with the last updates for Windows (preview updates from September, security updates from October). As a result, various problems with SSL and TLS connections can occur. Microsoft has therefore released some : out-of-band updates on October 17, 2022 to fix the problem.
The out-of-band updates KB5020439 and KB5020440 were added on October 18th. These updates are only available for download in the Microsoft Update Catalog and have to be installed manually (just search for the KB numbers). Details about these updates can be found in the linked KB articles.
So only Windows 11 22H2 is missing the corresponding fix update. EP writes here that this fix will be added with the upcoming update KB5018496. This is currently released in the Windows Insider program as a pre-release version in the Release Preview channel (see).
Problems fixed with the updates
People have asked in comments which applications are actually affected by the TLS bugs. I don’t have a complete list, but would like to give some hints below as to what has come to my attention as a fix. Thanks to blog readers for the pointers.
Advertising
Citrix connectivity issue
With the October 2022 updates, administrators found that Citrix clients could no longer communicate with Citrix netscalers. I had reported on this in the blog postCitrix connections broken after Windows update KB5018410 (October 2022) (TLS problem). Affected people who installed the above updates reported that this fixed the connection problem.
KB5020387 fixes TLS 1.3 problem on Windows 10
On Windows, there was also the issue that there TLS 1.3 implementation was buggy on Windows 10 (it only works in Windows 11). I had raised a conflict case in the blog post Bug: Outlook no longer connects to the mail server (October 2022). Microsoft suggested disabling TLS 1.3 via registry intervention as a workaround. In this comment, someone suggests uninstalling updates KB5018410 (Windows 10) and KB5018427 (Windows 11).
Blog reader Harvester asked here, whether TLS 1.3 works with Windows 10 after installing the special updates, and then followed up with the results of his own tests.
Self-reply after tests : Schannel is working properly after having applied KB5020387 on a LTSC 2021 IoT Enterprise image (21H2), where Schannel was previously broken (on build 19044.2130, from October 11 2022)
We initially guessed that the IoT Enterprise SKU wasn’t supporting TLS 1.3, but now we confirmed that we hit the bug mentioned in the post.
“Fun” fact : while it as initially reported that TLS 1.3 was available starting from Windows 10 1903, the Schannel documentation was changed recently, and now state that only Windows 11 and Server 2022 support TLS 1.3: Protocols in TLS/SSL (Schannel SSP)
VPN and WebEx Meetings App
Within this German comment blog reader Marten reported, that the WebEx Meetings App could no longer connect to the WebEx Server (OnPrem) via VPN. The issue has been fixed via update.
Quest Migration Manager for Exchange
On Twitter, enno0815de has sent the following tweet, which refers to my message about the out-of-band updates with TLS fix. It says, anyone planning a domain migration using Quest Migration Manager for Exchange should also install the updates. Otherwise, the account will be locked out for the migration.
In a follow up tweet he adds: By some circumstance the Atelia class (Quest component) is deleted from the registry. Without the TLS fix, you lock the user out of AD completely.
Over 45,000 VMware ESXi servers inventoried by Lansweeper just reached end-of-life (EOL), with VMware no longer providing software and security updates unless companies purchase an extended support contract.
Lansweeper develops asset management and discovery software that allows customers to track what hardware and software they are running on their network.
As of October 15, 2022, VMware ESXi 6.5 and VMware ESXi 6.7 reached end-of-life and will only receive technical support but no security updates, putting the software at risk of vulnerabilities.
The company analyzed data from 6,000 customers and found 79,000 installed VMware ESXi servers.
Of those servers, 36.5% (28,835) run version 6.7.0, released in April 2018, and 21.3% (16,830) are on version 6.5.0, released in November 2016. In total, there are 45,654 VMware ESXi servers reaching End of Life as of today
The findings of Lansweeper are alarming because apart from the 57% that enter a period of elevated risk, there are also another 15.8% installations that run even older versions, ranging from 3.5.0 to 5.5.0, which reached EOL quite some time ago.
In summary, right now, only about one out of four ESXi servers (26.4%) inventoried by Lansweeper are still supported and will continue to receive regular security updates until April 02, 2025.
However, in reality, the number of VMware servers reaching EOL today, is likely far greater, as this report is based only on Lansweeper’s customers.
VMWare versions detected on net scans(Lansweeper)
The technical guidance for ESXi 6.5 and 6.7 will carry on until November 15, 2023, but this concerns implementation issues, not including security risk mitigation.
The only way to ensure you can continue to use older versions securely is to apply for the two-year extended support, which needs to be purchased separately. However, this does not include updates for third-party software packages.
For more details about EOL dates on all VMware software products, check out this webpage.
What does this mean?
When a software product reaches the end-of-life date, it stops receiving regular security updates. This means that admins should have already planned ahead and upgraded all deployments to a newer release.
While it’s not unlikely that VMware will still offer some critical security patches for these older versions, it’s not guaranteed and certainly won’t release patches for all new vulnerabilities that are discovered.
Once an unsupported ESXi server has carried on for long enough without patches, it will have accumulated so many security vulnerabilities that attackers would have multiple ways to breach it.
Due to ESXi hosting virtual machines, attacking the server can potentially cause severe and wide-scale disruption to business operations, which is why ransomware gangs are so focused on targeting it.
More recently, Mandiant discovered that hackers found a new method to establish persistence on VMware ESXi hypervisors that lets them control the server and hosted VMs without being detected.
All that said, ESXi already enjoys ample attention from threat actors, so running outdated and vulnerable versions of the software would no doubt be a terrible idea.
Welcome to the most complete guide on WordPress speed optimization!
This is my attempt to sum up WordPress speed + core web vitals in 1 post (it’s loooong).
I’ve constantly updated it to reflect new changes ever since I first published this 10 years ago. You have updates to things like core web vitals, plugin changelogs, and Cloudflare Enterprise happening every day. While site speed has gotten complex, the basics have stayed the same: use lightweight themes/plugins on fast servers (ideally with a performant cache plugin/CDN).
Why this tutorial is different:
First, my recommendations on tools/plugins/services are arguably better than what other people tell you to use. I’m very transparent about SiteGround’s slow TTFB and cache plugin, Kinsta’s overpriced service + lack of resources, NitroPack being blackhat, RocketCDN’s poor performance, and Elementor/Divi being slow. I’ve also written extensive reviews/tutorials on nearly every major host, cache plugin, CDN, and core web vital you can find in my nav menu.
Which is the 2nd reason it’s different: configuration guides! I have tons of them. Need help configuring FlyingPress, LiteSpeed Cache, or Perfmatters? Want to improve TTFB or LCP? Or maybe you’re wondering which Cloudflare settings to use. I have detailed guides on all those.
If you have suggestions on making this tutorial better (or you have a question), drop me a comment. I’m all ears. I’m not for hire because I spend so much time writing these guides 🙂
Chrome Dev Tools – the coverage report shows your largest CSS/JS files and where they’re loaded from (plugins + third-party code are common culprits). So many parts of speed and web vitals are related to CSS/JS and it’s best to tackle it at the source. Removing things you don’t need is better than trying to optimize it.
KeyCDN Performance Test – measure TTFB in 10 global locations. This is mainly improved with better hosting and using a performant CDN with full page caching (like APO or FlyingProxy). It also shows DNS lookup times and TLS which can be improved with a fast DNS (i.e. Cloudflare) and configuring their SSL/TLS settings.
PageSpeed Insights – most items come down to reducing or optimizing CSS, JS, fonts, images, TTFB, and above the fold content. For example, preload your LCP image and exclude it from lazy load, then move large plugins/elements below the fold so they can be delayed. Focus on recommendations in PSI’s opportunities + diagnostics sections, and monitor your core web vitals report in Search Console.
CLS Debugger – see your website’s layout shifts (CLS) on mobile/desktop in a GIF.
WP Hive – Chrome extension that lets you search the WordPress plugin repository and see whether a plugin impacts memory usage and PageSpeed scores, but only measures “out of the box settings” and not when content is added to the frontend.
Wordfence Live Traffic Report – see bots hitting your site in real-time. AhrefsBot, SemrushBot, compute.amazonaws.com and other bots can be blocked if you’re using their service. Since most bot protection services don’t block these service’s bots, you’ll need to do this manually with something like Cloudflare firewall rules.
WP-Optimize – see which plugins add database overhead and remove old tables left behind by plugins/themes you deleted. Does a better than job cache plugins with scheduled cleanups because it can keep a certain number of post revisions while removing junk (cache plugins delete them all, leaving you with no backups).
cdnperf.com + dnsperf.com – you can these as baseline for choosing a DNS/CDN provider, but it doesn’t include StackPath’s CDN (removed from cdnperf and used by RocketCDN), QUIC.cloud’s CDN or CDN (used on LiteSpeed), and other services.
Waterfall Charts – testing “scores” isn’t nearly as effective as measuring things in a Waterfall chart. Google’s video on optimizing LCP is a great resource and shows you the basics. You can find one in WebPageTest, Chrome Dev Tools, and GTmetrix.
Diagnostic Plugins – the speed plugins section lists all plugins mentioned in the guide. It includes diagnostic plugins like Query Monitor (this is probably best for finding bottlenecks), WP Server Stats, WP Hosting Benchmark, and WP Crontrol.
2. DNS
A slow DNS causes latency which is part of TTFB (and TTFB is part of LCP).
Whoever you registered your domain through is who you’re using for a DNS. GoDaddy, NameCheap, and even Amazon Route 53 (used on Kinsta) don’t perform well on dnsperf.com. Better options include Cloudflare, QUIC.cloud, or Google (if using Google Domains). I usually recommend Cloudflare since it’s free and can be used on any setup by changing nameservers.
3. Hosting
Rocket.net with their free Cloudflare Enterprise will outperform any “mainstream host” since you get 32 CPU cores + 128GB RAM, NVMe storage, Redis, and Cloudflare’s full page caching + Argo Smart Routing. I use them and average a <150ms global TTFB (or click through my posts).
Combining a good host/CDN is arguably the best way to improve TTFB (using a host with improved specs on top of Cloudflare Enterprise hits 2 birds with 1 stone).
Mainstream hosts (like SiteGround, Hostinger, and WPX) don’t have a lot of CPU/RAM, use slower SATA SSDs, and are shared hosting with strict CPU limits which force you to upgrade plans. Cloud hosting is faster, but Kinsta still uses SATA SSDs with low CPU/RAM, PHP workers, and monthly visits (Redis also costs $100/month). Cloudways Vultr HF is who I previously used, but again, they start with only 1 CPU + 1GB RAM on slower Apache servers, PHP-FPM, and GZIP.
Here are Rocket.net’s:
All plans use 32 CPU cores + 128GB RAM with NVMe (faster than SATA), Redis (better than memcached), LiteSpeed’s PHP, and Brotli (smaller compression than GZIP). They have no PHP worker limits since only about 10% of traffic hits your origin due to their Cloudflare Enterprise.
SiteGround
Hostinger
Kinsta
Cloudways Vultr HF
Rocket.net
Hosting type
Shared
Shared
Cloud
Cloud
Private cloud
Storage
SATA
SATA
SATA
NVMe
NVMe
CPU cores
Not listed
1-2
12
1
32
RAM (GB)
Not listed
.768 – 1.536
8
1
128
Object cache
Memcached
x
Redis ($100/mo)
Redis (Pro)
Redis
Server
Nginx
LiteSpeed
Nginx
Apache
Nginx
PHP processing
FastCGI
LiteSpeed
FastCGI
FPM
LiteSpeed
Compression
Brotli
Brotli
Brotli
GZIP
Brotli
CPU limits
Very common
Low memory
Low PHP workers
Average
None
Why you need Cloudflare Enterprise
Because you get Enterprise features like 270+ PoPs, prioritized routing, full page caching, HTTP/3, WAF, and image optimization. 3 problems with most CDNs are their small network (PoPs) and no full page caching or image optimization. For example, WP Rocket’s RocketCDN uses StackPath which was removed from cdnperf.com and doesn’t include image optimization with a mediocre Tbps speed of 65+. SiteGround’s CDN only has 14 PoPs. QUIC.cloud CDN (for LiteSpeed) and BunnyCDN are good, but they still don’t beat Cloudflare Enterprise. Sure, you can pay $5/mo for Cloudflare’s APO, but you’re still missing out on all other Enterprise features.
3 popular hosts with Cloudflare Enterprise
Rocket.net’s Cloudflare Enterprise is free, setup automatically, and uses full page caching (unlike Cloudways). And unlike Kinsta’s, Rocket.net has Argo Smart Routing (specifically good for WooCommerce sites), load balancing, and image optimization. Rocket.net CEO Ben Gabler also used to be StackPath’s Chief Product Officer and went as far as building Rocket.net’s data centers in the same locations as Cloudflare’s. And unlike both hosts, Rocket.net doesn’t limit PHP workers (there’s no CPU limits) and monthly visit limits are 10-25 times more than Kinsta’s.
Cloudflare Enterprise (Kinsta)
Cloudflare Enterprise (Cloudways)
Cloudflare Enterprise (Rocket.net)
CDN PoPs
270
270
270
Prioritized routing
✓
✓
✓
Full page caching
✓
x
✓
HTTP/3
✓
✓
✓
WAF
✓
✓
✓
Argo smart routing
x
✓
✓
Load balancing
x
✓
✓
Image optimization
x
✓
✓
Automatic configuration
x
x
✓
Price
Free
$5/mo (1 domain)
Free
Problems with mainstream hosts
I’ve written some pretty bad reviews about SiteGround’s slow TTFB, CPU limits, and why SG Optimizer does a poor job with core web vitals (they also control several Facebook Groups and threaten to sue people who write bad reviews). Hostinger writes fake reviews and is only cheap because you get less resources like CPU/RAM. Kinsta and WP Engine are way too expensive for how many resources, PHP workers, and monthly visits you get. Along with major incidents like WPX’s worldwide outage and SiteGround’s DNS getting blocked by Google for 4 days (both WPX and SiteGround denied responsibility). One thing is clear: most mainstream hosts appear to be more interested in profits than performance. Please do your own research before getting advice.
Getting started on Rocket.net
Step 1: Create a Rocket.net account and you’ll be prompted to add a coupon. Sign up with coupon OMM1 to get your first month for $1 (renews at $30/mo or $25/mo when paying yearly). If you sign up with my coupon or affiliate links, I get a commission which I seriously appreciate.
Step 2: Request a free migration. They did this the same day and let me review my website before it was launched with no downtime. For the record, their support is better than Kinsta’s and you can reach out to Ben Gabler or his team (via phone/chat/email) if you have questions.
Step 3: Upgrade to PHP 8.1 and ask support to install Redis (they use Redis Object Cache). These are the only things I did since Cloudflare Enterprise and backups are both automatic.
Step 4: Retest your TTFB in SpeedVitals and click through your pages to see the difference. You can also search their TrustPilot profile for people mentioning “TTFB” where they’re rated 4.9/5.
I was previously on Cloudways Vultr HF which was great, but their Cloudflare Enterprise doesn’t use full page caching (yet) and is $5/mo with annoying challenge pages. Even if their Cloudflare Enterprise was identical, Rocket.net still outperforms them with better specs like more CPU/RAM, Brotli, and LiteSpeed’s PHP (plus better support, easier to use, and usually pricing). While Cloudways is a big improvement than most hosts, you’re already spending $18/mo for Vultr HF’s lowest 1 CPU plan with Cloudflare Enterprise. At that point, the extra $7/mo you’d be spending at Rocket.net is worth it. Rocket.net’s dashboard is also much easier.
For small sites on a budget, NameHero’s Turbo Cloud plan is similar to Hostinger between LiteSpeed, cPanel, and pricing. However, NameHero’s Turbo Cloud plan has about 1.5x more resources (3 CPU + 3GB RAM) with NVMe storage. NameHero’s support/uptimes are also better shown in TrustPilot reviews. This is one the fastest setups on a budget… you get a LiteSpeed server + LiteSpeed Cache + QUIC.cloud CDN, and email hosting. The main con is their data centers are only in the US and Netherlands. If these aren’t close to your visitors, make sure to setup QUIC.cloud’s CDN which has HTML caching (ideally the paid plan which uses all 70 PoPs).
4. Page Builders
Elementor/Divi are slower than Gutenberg/Oxygen.
Since multiple PSI items are related to CSS/JS/fonts, many people are replacing them with lightweight alternatives. The last thing you want to do is use a slow page builder then install a bunch of “extra functionality plugins” which add even more CSS/JS. Don’t fall into this trap. If you don’t want to ditch your page builder completely, there are still ways you can optimize it.
Divi/Elementor add extra CSS/JS/fonts to your site.
Adding more page builder plugins can slow it down more.
GeneratePress (what I use), Kadence, Blocksy, Oxygen are faster.
If using Elementor, try the settings under Elementor → Experiments.
Same thing with Divi (Divi → Theme Options → General → Performance).
If using Astra Starter Sites, use a template built in Gutenberg (not Elementor).
Use CSS for your header/footer/sidebar (instead of bloated page builder code).
Elementor has a theme customizer setting to host fonts locally + preload them.
If you don’t use Elementor font icons, disable them or use custom icons instead.
If you don’t use elementor-dialog.js for popups, disable it (i.e. using Perfmatters).
Many page builder plugins are module-based, so disable modules you don’t use.
Simplify your design by using less widgets/columns (here’s a YouTube video on it).
If you preload critical images in FlyingPress or Perfmatters, this excludes above the fold images from lazy load and preloads them to improve LCP. However, it doesn’t work with Elementor image widgets (go through your page builder + cache plugin documentation).
Background images aren’t lazy loaded by default because they’re loaded from a separate CSS file. Some cache plugins support a lazy-bg class you can use to lazy load backgrounds.
A performant CDN with HTML caching (and other CDN features) can be the difference maker. While cdnperf.com is a good baseline, there are other things to consider.
Start by looking at their network page (you’ll see BunnyCDN’s network has more PoPs and faster a Tbps than StackPath). Also look at the features (for example, RocketCDN only serves files from the CDN and nothing else while other CDNs do a lot more than just “serving files.” Cloudflare’s dashboard has hundreds of optimizations to improve speed, security, and CPU usage. Aside from choosing a good CDN, make sure to also take advantage of everything it offers. Or just use a service like FlyingProxy/Rocket.net that integrates Cloudflare Enterprise.
Cloudflare – it’s hard to beat Cloudflare with 270+ data centers and all the robust features. Open your Cloudflare dashboard and use the recommendations below to configure settings.
Free Cloudflare Features I Recommend Using
CDN – in your DNS settings, find your domain and change the proxy status to Proxied (orange cloud). This is needed for several Cloudflare features to work.
TLS version – set minimum TLS version to 1.2 and make sure TLS 1.3 is enabled.
Firewall rules – often used to block access to wp-login, XML-RPC, and “hacky” countries. Firewalls block attacks along with unwanted requests to the server.
Bot protection – block spammy bots from hitting your server. I would also check your Wordfence live traffic report to see bots hitting your website in real time and manually block bots like AhrefsBot + SemrushBot if you don’t use them. Bot fight mode can add a JS file to your site (invisible.js) and cause PSI errors (so test this).
Brotli – this only works if your host supports Brotli, otherwise GZIP will be used.
Early hints – while the server is waiting for a response, preload/preconnect hints are sent to the browser so resources load sooner, reducing your server think time.
Browser cache TTL – 1 year is good for static sites (my blog is mostly static so this is what I use) or use 1 month for dynamic sites. This is recommended by Google and can fix serve static assets with an efficient cache policy in PageSpeed Insights.
Crawler hints – helps search engines efficiently time crawling and save resources.
Cache reserve – improves cache hit ratio by making sure specific content is being served from Cloudflare even when the content hasn’t been requested for months.
Workers – deploy code on Cloudflare’s edge servers (try the playground). Workers are serverless with automatic scaling + load balancing. Obviously involves coding knowledge and can reduce LCP by 80%. It can also be used for external cron jobs.
Cache everything page rule – most common page rule which caches HTML and improves TTFB, but I recommend APO or Super Page Cache for Cloudflare instead.
HTTP/3 – not true HTTP/3 but still a nice feature (test your site using HTTP/3 test).
0-RTT connection resumption – good for repeat visitors, latency, mobile speed.
Hotlink protection – saves bandwidth by stopping people from copying your images and using them on their own website while they’re hosted on your server.
Zaraz – offload third-party scripts to Cloudflare like Google Analytics, Facebook Pixel, chatbots, and custom HTML. But test your results against delaying these.
Monitor bandwidth/analytics – the more bandwidth you offload to Cloudflare the better. This should lighten the load on your server while reducing CPU usage.
Paid Cloudflare Features
APO – caches HTML which can improve TTFB in multiple global locations.
WAF – block unwanted requests, improve security, and reduce CPU usage.
Argo + Tiered Cache – route traffic using efficient paths with Tiered Cache.
Image optimizations – I prefer these over plugins. Between all 3 (image resizing, Mirage, Polish), you don’t have to use a bloated image optimization plugin and they usually do a better job. You have features like compression/WebP and they also have mobile optimizations like serving smaller images to reduce mobile LCP.
Signed Exchanges – improves LCP when people click links in Google’s search results via prefetching which Google says can lead to a substantial improvement.
Load Balancing – creates a failover so your traffic is re-routed from unhealthy origins to healthy origins. Can reduce things like latency, TLS, and general errors.
Cloudflare Enterprise – majors benefits include prioritized routing, more PoPs, Argo + Tiered Cache, full page caching, image optimization, and other features depending where you get it from. The easiest/cheapest way is to use a host with Cloudflare Enterprise or FlyingProxy (I recommend Rocket.net’s who even built their data centers in the same locations as Cloudflare). It’s just more thought out than Cloudways/Kinsta. You could also consider using Cloudflare Pro which has some of these features. It requires more configuration but gives you more control.
Take advantage of different caching layers your host offers
BunnyCDN – Gijo suggests Cloudflare + BunnyCDN which is what I’ve used for a long time. If you’re using FlyingPress, FlyingCDN is powered by BunnyCDN with Bunny Optimizer + geo-replication. It’s also cheaper than buying these directly through BunnyCDN and easy to setup.
QUIC.cloud – use this if you’re on LiteSpeed. You’ll want to use the standard (paid) plan since the free plan only uses 6 PoPs and doesn’t have DDoS protection. It has HTML caching which is similar to Cloudflare’s full page caching and is also needed for LSC’s image/page optimizations.
RocketCDN – uses StackPath which was removed from cdnsperf.com and has less PoPs, slower Tbps, no image optimization, no HTML caching, and no other features besides serving files from a CDN. Also isn’t “unlimited” like WP Rocket advertises since they will cut you off at some point.
SiteGround CDN – not a lot of PoPs/features and you have to use their DNS to use it (which if you remember, was blocked by Google for 4 days). I personally wouldn’t trust this with my site.
6. Cache Plugins
Let’s summarize 5 popular cache plugins in 10 lines or less.
FlyingPress – optimizes for core web vitals and real-world browsing better than the last 3. When a new core web vital update comes out (like fetchpriority resource hints), Gijo is almost always first to add it. Awesome features not found in most cache plugins: preloading critical images lets you set the number of images usually shown above the fold to exclude them from lazy load while preloading them. FlyingPress can also lazy render HTML elements, self-host YouTube placeholders, and it has a lazy-bg helper class for lazy loading background images. FlyingCDN uses BunnyCDN with Bunny Optimizer + geo-replication (great choice). The remove unused CSS feature is faster than WP Rocket’s since it loads used CSS in a separate file (instead of inline) which Perfmatters agrees is faster for visitors. Really, the main thing it doesn’t have is server-level caching. I moved from WP Rocket to FlyingPress and saw a big difference in speed.
SG Optimizer
WP Rocket
FlyingPress
Server-side caching
✓
x
x
Delay JavaScript
x
✓
✓
Remove unused CSS
x
Inline
Separate file
Critical CSS
x
✓
✓
Preload critical images
x
x
By number
Exclude above the fold images
By class
By URL
By number
Lazy load background images
x
Inline
Helper class
Fetchpriority resource hint
x
x
✓
Lazy render HTML elements
x
x
✓
Add missing image dimensions
x
✓
✓
YouTube iframe preview image
x
✓
✓
Self-host YouTube placeholder
x
x
✓
Host fonts locally
x
x
✓
Font-display: swap
x
✓
✓
Preload links
x
✓
✓
CDN (beyond Cloudflare)
SiteGround CDN
StackPath
BunnyCDN
CDN PoPs
14
60
93
CDN Tbps
N/A
65
80
Dynamic caching
✓
x
x
CDN geo-replication
x
x
✓
CDN image optimization
✓
x
✓
CDN image resizing for mobile
x
x
✓
Documented APO compatibility
x
x
✓
LiteSpeed Cache – also does a great job optimizing for web vitals and real users, but different than FlyingPress. Mainly because it should only be used on LiteSpeed, it’s free, and it has faster server-side caching. However, the settings can be complicated. While some settings are similar to FlyingPress like loading used CSS in a separate file and lazy loading HTML elements, it has its own unique features such as localizing third-party resources, ESI, guest mode, LQIP, and HTML caching through QUIC. Use LSC if you’re on a LiteSpeed host. Anything else, I’d use FlyingPress.
WP Rocket – removing unused CSS is slower for visitors and RocketCDN isn’t a good CDN. WP Rocket doesn’t self-host fonts (or even recommend it) or video placeholders. Excluding above the fold images from lazy load and preloading them individually is tedious. Still no image optimization or documented APO compatibility. While Gijo releases many new features and updates FlyingPress to address core web vital updates, it seems WP Rocket has fallen behind. Two good things about WP Rocket are automatic delaying of JavaScript and documentation.
SiteGround Optimizer – great for caching, not for web vitals. Lacks way too many features and has a history of compatibility issues the developers blame on third-party plugins/themes if you check support threads. My advice is to only use it for caching, disable everything else, then use FlyingPress or WP Rocket (just make sure page caching is only enabled in 1 plugin and disabled in the other). Of course, SiteGround will glorify their cache plugin even when it’s clearly inferior.
NitroPack – don’t use this! The only reason you get better “scores” is because it moves elements off the main-thread so they can’t be detected in speed testing tools. This leads to great (but false) scores and it doesn’t actually do a good job making your website load faster compared to other plugins. Google “NitroPack blackhat” and you’ll find plenty of articles on it.
7. Other Caching
Cache plugins are just 1 layer.
Check whether your host supports object cache (Redis/memcached), OPcache, and HTTP accelerators like Varnish/FastCGI. Most do but they need to be enabled or set up manually.
You also have CDN caching which is its own layer. All these are meant for different things and you should ideally use most (if not all) them. People get scared they’re using too much caching, but as long as you’re only using 1 type of layer (not both Redis + memcached), it’s a good thing.
OPcache – enable in your host (can help reduce CPU usage).
Browser cache – enable in your cache plugin (stores files in browsers).
HTTP accelerators – enable in your host (probably Varnish or FastCGI).
Object cache – Redis generally uses memory more efficiently than memcached and is good for large/eCommerce sites. Once it’s enabled in your host, you’ll connect it your site using a plugin (i.e. LiteSpeed Cache, W3 Total Cache, SG Optimizer, WP Redis). Check your host’s documentation/support on which plugin is best. For example, Rocket.net requires you to install the WP Redis plugin while Cloudways requires you to install the Redis addon.
CDN cache – APO is not the same as a cache everything page rule or the Super Page Cache plugin. QUIC also does HTML caching, then there are services that include Cloudflare’s full page cache like Rocket.net’s Cloudflare Enterprise, FlyingProxy, and SiteGround Optimizer. The key thing is that you’re caching HTML somewhere as it can significantly improve TTFB.
Take advantage of different caching layers your host offers
8. Plugins
Watch out for plugins that:
Add CSS/JS to the frontend – use the Chrome Dev Tools coverage report to see which plugins add CSS and JS. This includes plugins that inject third-party JavaScript or fonts.
Increase CPU usage – common with plugins that collect “statistics” like Wordfence’s live traffic report, Query Monitor, and Broken Link Checker. But can really be from any plugin. WP Hive tells you if a plugin increases memory usage when browsing the WP plugin repo.
Add database bloat – use WP-Optimize to see which plugins (or specific plugin modules) add the most database overhead. This is explained more in this guide’s database section.
Load above the fold – slow plugins are bad enough, but loading them above the fold is even worse. When plugins load below the fold, you can delay them (i.e. comment plugins).
Use jQuery – Perfmatters has a script manager setting to show dependencies. Once it’s enabled, head to the script manager → jQuery and it shows you all plugins using jQuery. Felix Arntz wrote an article on how removing jQuery can reduce JavaScript by up to 80%.
Security – no security plugin (Cloudflare, firewall, etc).
Sliders – Soliloquy or MetaSlider (but ideally no sliders).
Analytics – call me crazy but I only use Google Search Console.
SEO – Rank Math or SEOPress (but most SEO plugins use jQuery).
CSS – need custom styling or even a table of contents? Just use CSS.
Backups – hosting backups or a lightweight alternative like UpdraftPlus.
In Query Monitor, the “queries by component” section shows your slow plugins. You can also use my list of 75+ common slow plugins. Finally, delete all plugins you’re not using (as well as their database tables in WP-Optimize), and disable plugin features/modules you’re not using.
Plugin
Category
Memory Impact
PageSpeed Impact
All In One SEO
SEO
x
x
Broken Link Checker
SEO
x
✓
Disqus
Comments
✓
x
Divi Builder
Page Builder
x
x
Elementor
Page Builder
x
x
Elementor Premium Addons
Page Builder
✓
x
Elementor Pro
Page Builder
x
x
Elementor Ultimate Addons
Page Builder
✓
x
JetElements
Page Builder
x
x
Jetpack
Security
x
x
NextGEN Gallery
Gallery
x
x
Popup Builder
Popup
x
x
Site Kit by Google
Analytics
x
✓
Slider Revolution
Slider
x
x
Social Media Share Buttons
Social Sharing
✓
x
WooCommerce
WooCommerce
x
x
Wordfence
Security
x
✓
wpDiscuz
Comments
x
x
WPML
Translate
x
x
Yoast SEO
SEO
x
✓
9. CSS + JavaScript
Probably the #1 reason for poor core web vitals.
New Optimizations
Remove unused CSS – WP Rocket’s method of loading used CSS inline is slower for visitors but better for scores. You should ideally use FlyingPress, LiteSpeed Cache, or Perfmatters for this which loads used CSS in a separate file so it can be cached and doesn’t increase HTML size. You should only be using 1 plugin for this. If you’re not using an optimization plugin that does this, try DeBloat or PurifyCSS.
Remove Gutenberg CSS – if you don’t use Gutenberg’s block library (i.e. you’re using classic editor), you can remove Gutenberg’s CSS which is loaded by default.
Asset unloading plugins – remove CSS/JS (or entire plugins) from specific pages/posts where they don’t need to load. Common examples are only loading contact forms on the contact page, only loading social sharing plugins on posts, and disabling WooCommerce plugins where they’re not used. You can also disable specific files like jQuery and elementor-dialog if you don’t use them. I recommend Perfmatters especially if you’re using WP Rocket or SiteGround Optimizer because it has many optimizations not found in these plugins. Be sure to use test mode and dependencies in your script manager settings. For a free plugin, try Asset CleanUp.
Critical CSS – loads above the fold CSS immediately which improves LCP. Most cache plugins do this while others (like SG Optimizer) don’t. If you make changes to stylesheets or custom CSS, regenerate critical CSS so it’s current with your site.
Load CSS/JS non render-blocking – both deferring JavaScript and critical CSS help serve resources non render-blocking. Make sure they work in your cache plugin and exclude files from defer if they break your site. Or try Async JavaScript.
Don’t combine – should almost always be off especially on big sites or on HTTP/2.
Optimizations Covered In Other Sections
Page builders – Elementor/Divi add extra CSS/JS which can be optimized with their built-in performance settings, coding your header/footer/sidebar in CSS, disabling Elementor fonts/dialog, lazy loading background images in CSS, etc.
Plugins – just look at the screenshot below (plugins are obviously a major factor).
Third-party code – hosting files locally, delaying JavaScript, and using a smaller GA tracking code can reduce its size or delay so it doesn’t impact initial load times.
Font Icons – disable these if you don’t use them or use Elementor’s custom icons.
WooCommerce – disable scripts/styles on non-eCommerce content and disable Woo plugins where they don’t need to load (many load across the entire website).
This is anything on your site that has to pull info from a third-party domain (like Google Fonts, Google Analytics tracking code, or an embedded YouTube video). It’s a common reason for JS-related errors in PSI. Luckily, most of it can be optimized especially if it’s shown below the fold.
Step 1: Host files locally – some third-party code can be hosted locally (see the table below). LiteSpeed Cache can localize resources, FlyingPress can host fonts/YouTube thumbnails locally, Perfmatters does fonts and analytics, and WP Rocket does nothing.
Third-Party Code
URL(s)
Plugins To Host It Locally
Google Fonts
fonts.gstatic.com
Most optimization plugins, Elementor, OMGF
Google Analytics
google-analytics.com
Flying Analytics, Perfmatters
Gravatars
gravatar.com
Simple Local Avatar
YouTube Thumbnails
i.ytimg.com
FlyingPress, WP YouTube Lyte
Step 2: Delay JavaScript – for third-party code that can’t be hosted locally, delay its JavaScript if it’s loading below the fold (you can also delay plugins loading below the fold). WP Rocket does this automatically while other cache plugins make you add files manually. If your cache plugin doesn’t support this, use Perfmatters or Flying Scripts. In these, you’ll set a timeout period and can increase this if you’re not seeing good results. You can try offloading third-party code to Cloudflare Zaraz, but I prefer delaying its JS.
Step 3: Prefetch or preconnect everything else – for all third-party code that can’t be hosted locally or delayed, add a DNS prefetch resource hint. Preconnect is usually only used for CDN URLs (not needed for Cloudflare), and third-party fonts (should be hosted locally). Or YouTube if you can’t eliminate requests using video optimizations in step #13.
Google Analytics – Perfmatters + Flying Analytics can use a minimal analytics tracking code that’s just 1.5 KB. Perfmatters can also prevent a Doubleclick request by disabling display features, but both these should only be used if you don’t need certain data in GA.
Avoid overtracking – one of the most common “mistakes” I see is sites using too many tracking tools: Analytics, Tag Manager, Heatmaps, Pixel, etc. Do you really need them all?
11. Fonts
Probably your largest files after CSS/JS.
Your GTmetrix Waterfall chart shows font load times, number of requests, and whether they’re served locally or from a third-party domain like fonts.gstatic.com or use.fontawesome.com. Be sure to keep tabs on your Waterfall chart as you make optimizations. Fonts can also cause FOIT and FOUT which cause layout shifts. A few simple tweaks can make your fonts load much faster.
Reduce font families, weights, icons – try to only use 1 font family and only load the weights you actually use. Disable Font Awesome and Eicons if you don’t use them (Elementor has a tutorial on this). Some fonts also have larger file sizes than others.
Use WOFF2 – the most lightweight/universal format which is faster than .ttf and .otf.
Host locally – if your fonts are being served from fonts.gstatic.com, host them locally.
Preload – fonts should be preloaded when they load above the fold or used in CSS files. Most cache/optimization plugins require you to manually add font files (and if there’s a crossorigin option like in Perfmatters, it should be used for fonts). Elementor hosts fonts locally and preloads them under Theme Customizer → Performance. PSI used to tell you which fonts to preload in “preload key requests” but I don’t think they do this anymore.
Add font-display: optional – if you need to “ensure text remains visible during webfont load,” add font-display: optional to your font’s CSS. This is recommended by Google for the fastest performance while preventing layout shifts. It delays loading text up to 100ms. As of writing this, most plugins only support swap found in Elementor, Perfmatters, and most cache plugins. To use optional, you need to add it manually to your font’s CSS, use WP Foft Loader, or use swap until your optimization plugin supports optional. Preloading fonts that use font-display: optional completely eliminates layout shifts (FOIT) from fonts.
System fonts – system fonts generate 0 requests and are obviously best for speed, but even for someone who obsesses over performance, I’d rather have a better looking font.
Use custom Icons for Elementor – replace Font Awesome and Eicons with custom icons.
Serve Google Fonts from Cloudflare Workers – I’ll leave this here if you want to dive in.
12. Images
There are 7 PSI items related to image optimization, and that doesn’t even cover everything.
Preload critical images and exclude them from lazy load – above the fold content should load immediately which is a big factor of LCP. Instead of delaying images with lazy load, you want the browser to download them immediately by using preload. The easiest way to do this (by far) is “preload critical images” in FlyingPress or Perfmatters. Instead of manually excluding/preloading above the fold images on every single page/post (because they’re usually different), you will set the number of images usually shown above the fold. In my case, it’s 3. This will preload your top 3 images while excluding them from lazy load. Currently, FlyingPress is the only cache plugin I know that supports fetchpriority which is recommended by Google to set things like your LCP image to “high priority.” Props to Gijo.
Exclude above the fold images from lazy load and preload them
LCP image – your most important image to optimize for lower LCP (shown in PSI).
Background images – page builders serve background images in their CSS and won’t be lazy loaded, leading to ‘defer offscreen images’ errors. Some cache plugins have a lazy-bg helper class, Perfmatters has a CSS background images setting, and WP Rocket makes you move them to inline HTML. Check the documentation in your cache/image optimization plugin on how to lazy load them. You can also use Optimal or add a helper class yourself.
Image CDNs – I use Cloudflare for image optimization but Bunny Optimizer and QUIC are good too. They usually do a better job than plugins (and it’s 1 less plugin on your website).
Resize images for mobile – make sure your image optimization plugin (or image CDN) serves smaller images to mobile which should also improve your LCP on mobile. This is the “image resizing” feature in Cloudflare, or you could use ShortPixel Adaptive Images.
Properly size images – resize large images to be smaller. My blog is 765px width so I crop/resize blog images to that size (the Zoom Chrome Extension is handy for getting the perfect dimensions when taking screenshots). I always recommend creating an “image dimensions cheat sheet” so you know the size of your blog, featured, sidebar images, etc.
WebP – faster than JPEG/PNG and most image optimization plugins or CDNs can do this.
Compression – Lighthouse test images at 85% so that’s usually a good compression level.
CSS sprites – combines multiple small/decorative images into 1 image so it only creates 1 request. My old homepage used a CSS sprite and it was very fast. You can do it for sections like “featured on” where you show a bunch of logos. You would use a CSS sprite generator.
Specify dimensions – most cache plugins can “add missing dimensions” otherwise you would need to add a width/height to the image’s HTML or CSS. This prevents layout shifts.
Downgrade quality on slow connections – services like Cloudflare Mirage + Optimole serve low quality images on slow connections until a faster connection can be accessed.
Hotlink protection – stops people from using your images when they’re hosted on your server and saves bandwidth. Common with sites using high quality images or if people copy your content. Can be enabled in your host or by using Cloudflare’s hotlink protection.
Low quality images placeholders (LQIP) – if you’re using QUIC.cloud on LiteSpeed, these can prevent layout shifts but you need to make sure you’re doing it right or it will look bad.
13. Videos
Unless videos are optimized, they will probably be the slowest thing on a page.
While most cache plugins lazy load videos and replace iframes with a preview image, FlyingPress and WP YouTube Lyte are some of the only plugins that optimize placeholders.
Lazy load videos – done in cache plugins, Perfmatters, or try WP YouTube Lyte.
Replace YouTube iframes with preview images – the iframe (which is the heaviest element of the video) is only loaded once your visitors actually click the play button.
Self-host YouTube placeholders – FlyingPress and WP YouTube Lyte can self-host placeholders to prevent i.ytimg.com requests shown in your “third-party code” report.
Preconnect – if you’re not able to make the optimizations above and you still have third-party domains loading from YouTube, you can preconnect domains from youtube.com, i.ytimg.com, and Roboto which is currently being used as the font in the YouTube player.
View your “longest main-threads tasks” report in PageSpeed Insights and optimize those files. LCP includes 4 sub-parts and Google’s YouTube video is a nice resource for optimizing each one.
Most LCP recommendations are scattered in this guide, so I’ll just go over them briefly.
Exclude above the fold images from lazy load – you should never lazy load, delay, or defer anything that loads above the fold because this content should load immediately, which is why you should also use preload hints to help browsers download them faster.
Prioritize above the fold images – preload above the fold images (or use fetchpriority). PSI shows your largest contentful paint image which is the most important to optimize.
Reduce CSS, JS, font sizes – a big part of reducing load time is reducing their file sizes.
Reduce TTFB – 40% of LCP can usually be improved with a better hosting + CDN setup.
Eliminate render-blocking CSS/JS – render-blocking resources add delay (see video).
Use font-display: optional – if fonts aren’t loaded properly, they can also add delay.
Lazy render HTML elements – allows browsers to focus on the above the fold content.
Preload, preconnect, prefetch – hints browsers to download specific resources faster.
Increase cache expiration – also mentioned by Google (Cloudflare browser cache TTL).
Choose the right cache plugin/settings – some have better optimizations than others.
Enable Signed Exchanges (SXGs) – this is found in Cloudflare (Speed → Optimization).
Use Cloudflare Workers – Google Engineer used Workers to improve LCP by about 80%.
Move plugin content, ads, animations below the fold – that way, they can be delayed.
16. CLS
Layout shifts happen when things jump around while the page is loading.
You can use Google’s layout shift debugger to see these in a GIF. PSI also has an “avoid large layout shifts” item showing you which sections on your website contribute the most to CLS. Even with these recommendations, it’s hard to know why the section is causing a layout shift.
Change font-display to swap or optional – do this if you see “ensure text remains visible during webfont load.” As shown in section #11, font-display: optional is the best method.
Problems with loading CSS asynchronously – this is a setting in cache plugins that can add layout shifts caused by FOUC (flash of unstyled content). Ideally use the “remove unused CSS” method instead. If this breaks your site and you default back to loading CSS asynchronously, make sure you exclude problematic files causing FOUC, ensure critical CSS is working, and always regenerate critical CSS after updating stylesheets/custom CSS.
Preload fonts – preloading fonts eliminates layout shifts when they use display: optional.
Specify dimensions of images, videos, iframes, ads – the first 3 are easy (make sure a width and height are specified in images). Ads and other dynamic content should have reserved space by placing it in a div code. The width/height should be the ad’s largest size.
Use CSS transform in animations – not a fan of animations but here’s documentation.
Use separate mobile cache (when it makes sense) – if your mobile site is different than desktop and you’re not using a separate mobile cache, it can cause layout shifts. However, you’ll need to check your cache plugin’s documentation on when to use (and not use) this.
Change cookie notice plugin – search your plugin’s support thread. It’s been reported some cookie plugins cause layout shifts. I recommend Gijo’s solution or this Cookie plugin.
17. Preload, Prefetch, Preconnect
These help browsers download high priority resources faster.
They prioritize above the fold content (preload + fetchpriority). Preload is also used in Cloudflare’s Early Hints and for downloading internal pages in the background so they load faster when visitors click them (link preloading + Flying Pages). Prefetch + preconnect help establish early connections to third-party domains if resources aren’t already being delayed.
Preload – commonly used for above the fold images (this can also be a WebP image) but can also be used for CSS/JS (i.e. the block library), videos, audio, Cloudflare workers, and other files.
Fetchpriority – similar to preload only assigns a priority (low, high, auto). For example, if you have a large LCP image, you would assign that image’s priority to “high.” But if you have an image carousel that’s loading above the fold, you could assign the images with a low priority. FlyingPress is the only plugin I know currently supporting fetchpriority shown in the changelog.
<img src="lcp-image.webp" fetchpriority="high">
Link preloading – there’s 2 main types: preloading links in the viewport so internal links in the immediate content load faster when clicked (supported by Flying Pages and FlyingPress). And “link preloading” where users hover over any internal link (or touch it on mobile), and the page will download in the background so by the time they actually click it, it appears to load instantly (found in cache plugins like WP Rocket). While neither improves scores, both improve perceived load time. Just be careful… preloading too many pages in the background will increase CPU usage especially if you have something like a WooCommerce store with internal links in images. If visitors are hovering over product images, this will cause lots of pages to download. Not good!
DNS Prefetch – this helps browsers anticipate third-party domains by performing a DNS lookup, but usually not needed since third-party domains should be hosted locally or delayed.
Preconnect – establishes early connections to important third-party domains. Common with CDN URLs and third-party fonts like fonts.gstatic.com, use.fontawesome.com, and use.typekit. Most cache plugins add preconnect automatically when you add a CDN URL or when enabling “Google Font Optimization” (or a similar setting), but you’ll want to check their documentation.
You can use Perfmatters or Pre* Party if your optimization plugin doesn’t support a specific resource hint
18. Database
There’s usually 3 problems with using your cache plugin to clean your database:
It can’t take database backups.
It can’t remove database tables left behind by old plugins.
It deletes all post revisions, but you may want to keep a few.
That’s why I recommend WP Optimize for database cleanups. Go through your database tables and look for tables that are not installed or inactive. You can delete these if you don’t plan on using the plugin (or theme) again since they will usually store info in the database for future use.
Certain plugin modules/features can also add lots of overhead especially if they collect data. Rank Math’s Google Analytics module adds lots of overhead, so consider disabling this Rank Math module and getting your analytics data directly from the Google Analytics website instead.
For ongoing database cleanup, WP-Optimize removes everything most cache plugins do, but it lets you keep a certain amount of post revisions so you have backups (I recommend 5-10). You can also connect UpdraftPlus which takes a database backup before scheduled optimizations.
19. Background Tasks
Background tasks can bog down your server and increase CPU usage.
These are common with cache plugins (preloading + automatic cache clearing), plugins that collect stats or create autoloads, and even WordPress core (Heartbeat, autosaves, pingbacks). Many of these can be disabled, limited, or scheduled during non-peak hours using a cron job.
Control Preloading – the preloading in cache plugins is infamous for increasing CPU usage (WP Rocket’s preloading, LSC crawler, SG Optimizer’s preheat cache, etc). The first step is changing settings to only preload important sitemap URLs (i.e. page-sitemap.com + post-sitemap.com) instead of the full sitemap. Next, you can increase the preload interval.
Only preload important sitemap URLs (not the full sitemap)
Automatic cache clearing – there are specific actions that trigger your entire cache to be cleared (and when the cache lifespan expires). Instead of constantly clearing cache with these actions, disable automatic cache clearing and use a cron job to clear it at a specific time (once at night). It’s best to use a cron job for both cache clearing + cache preloading.
Disable WP-Cron – using an external cron to schedule tasks like the 2 items above helps reduce CPU usage. The first step is to add the code below your wp-config.php file. Next, setup a real cron job in your host, Cloudflare, or using a third-party service like EasyCron. Some hosts have specific instructions for adding a cron job, so check their documentation.
Scheduling tasks using cron jobs for 5-10 minutes can reduce CPU usage
Remove unused CSS – decrease WP Rocket’s batch size and increase the cron interval.
Link preloading – some cache plugins can “preload links” which sounds like a good idea because when users hover over a link, that page downloads in the background to make it load faster by the time users actually click it. But if your website has lots of links (such as a WooCommerce store with links in the product images), you’ll want to leave this setting off.
Plugins – think of Query Monitor, Wordfence’s live traffic report, and backup/statistic plugins (they all run background tasks). You might be able schedule these, disable specific features in plugins, or delete the plugin completely. Plugins/themes can also leave behind autoloaded data when you delete them which can be cleaned up in the wp_options table.
Autosaves – when you’re editing a post, WordPress autosaves a draft every minute. You can use a simple line of code (or Perfmatters) to increase this to something like 5 minutes.
define('AUTOSAVE_INTERVAL', 300); // seconds
Heartbeat – called every 15s and can usually be disabled in the frontend/backend, then limited in the post editor since you probably want to keep features there (like autosaves).
Pingbacks – disable pingbacks since you don’t want a notification every time you add an internal link. You may want to leave trackbacks on to help notify blogs you linked to them.
Post revisions – stored every time you hit save, publish, or update and accumulate over time. You can limit revisions in some optimization plugins, manually with code, or use WP-Optimize to run scheduled database cleanups while keeping a certain number of revisions.
define( 'WP_POST_REVISIONS', 10 );
Plugin data sharing – disable in plugins to save a little resources, sorry plugin developers!
Bots – blocking spam bots and using Cloudflare’s crawler hints saves resources from bots.
Comment spam – I use Antispam Bee and blacklist these words in the Discussion settings.
Hosting features – WP Johnny has nice tips on disabling unused services in your hosting account like the DNS, email, FTP/SFTP, proxies, or other services if you’re not using them.
Bloat removal plugins – using plugins like Unbloater + Disable WooCommerce Bloat help.
20. Mobile
Poor mobile scores in PSI is a common issue. Most desktop optimizations transfer over to mobile so start with “general optimizations” first. Otherwise, here are mobile-specific tips.
Resize images for mobile – image CDNs and adaptive image plugins do this.
Reduce latency – use a faster DNS, faster TLS versions, and Cloudflare’s 0-RTT.
Replace sliders/galleries with static images – use responsive editing to do this.
Remove unused CSS/JS – Perfmatters can disable unused CSS/JS by device type.
Don’t use AMP – lots of challenges and most WordPress users agree not to use it.
Fix mobile layout shifts – Google’s layout shift debugger tests mobile layout shifts.
Use mobile caching – enable this in your cache plugin or use one that supports this.
Know when to use separate mobile cache – check your cache plugin documentation.
Downgrade image quality on slow connections – try Cloudflare Mirage or Optimole.
Check your responsiveness – even if you use a responsive theme, check this manually.
Add a “load more comments” button on mobile – helps if you have lots of comments.
Most image CDNs serve smaller images to mobile (but not RocketCDN)Disable specific files/plugins from loading on mobile in Perfmatters
21. WooCommerce
WooCommerce sites often have more plugins, scripts, styles, and are more resource-hungry than static sites. You will need to optimize your website even more if you want good results.
Hosting – wphostingbenchmarks.com ran tests for multiple WooCommerce hosts, although I think there are much better options than the ones tested (I would personally lean towards something like Rocket.net, GridPane, RunCloud). Obviously very important.
Remove WooCommerce admin bloat – Disable WooCommerce Bloat is good for this.
Cloudflare Argo + Tiered Cache – specifically good for speeding up dynamic requests.
Redis – also specifically good for WooCommerce (especially Redis Object Cache Pro).
Go easy on WooCommerce Extensions – just like other plugins, be minimal with these.
Unload WooCommerce plugins – Woo plugins are infamously bad with loading across your entire site. Use your asset unloading plugin to disable them where they’re not used.
Use Cloudflare firewall rules (i.e. only access wp-login from your IP).
Disable file editing to prevent hackers from editing theme/plugin files.
Follow security-related social media accounts like Cloudflare/Wordfence.
Check for known vulnerabilities before updating things (especially plugins).
23. PHP Version
Only 7% of websites use PHP 8.
Come on y’all, you already know higher PHP versions are faster and more secure. Google “update PHP version [your host]” and you’ll find instructions. If updating breaks your site, just revert back to your older version (or remove incompatible plugins that aren’t maintained well).
PHP version used by WordPress sites (source: WordPress stats)
24. Make Sure Optimizations Are Working
You set things up, but are they working? Make sure they are.
Caching – cache plugins should have documentation to check if the caching is working.
Redis/memcached – LiteSpeed Cache’s connection test and most Redis plugins tell you.
Confirm Redis is working (screenshot is in LiteSpeed Cache)
CDN Analytics – how many requests are you blocking from bots, hotlink protection, and WAF? What is your cache hit ratio (hopefully around 90%)? CDN analytics are very useful.
Dr. Flare – Chrome Extension to view tons of Cloudflare stats like your cache hit ratio, uncached requests, non-Cloudflare requests, how much % was reduced by Polish/Minify.
CDN rewrites – are your files actually being served from your CDN? Check your CDN Analytics, Dr. Flare, or view your source code to make sure files are being served from the CDN when using a CDN URL, like this: cdn.mywebsite.com/wp-content/uploads/logo.png. If you’re using BunnyCDN, you may be able to serve more files from BunnyCDN by adding your CDN URL to your cache plugin on top of using BunnyCDN’s plugin. It worked for me.
APO – verify Cloudflare’s APO is working by testing your website in uptrends.com then making sure headers exactly match with what Cloudflare shows in the documentation.
Confirm APO is working by checking headers
Asynchronous CSS – if you’re using this, cache plugins should also have documentation.
External cron jobs – check the logs in your hosting account to make sure these are firing.
Waterfall charts – after each optimization, you should ideally check its impact using a Waterfall chart (better than running another PageSpeed Insights test and testing scores).
Clear cache – you may need to clear cache or regenerate critical CSS to see your changes.
Obviously you don’t need all these especially if you’re using a cache/optimization plugin that already does some of these, Cloudflare image optimizations, or you can code things manually.
Plugins like Perfmatters have great documentation.
Gijo Varghese and WP Johnny also put on quality articles.
My other articles (if you liked this one, I have plenty more).
Hire Help
BDKamol – Pronaya mainly works with Gutenberg, WooCommerce, and Genesis. He’s been helping me for over 10 years even when I launched my first website and had no visitors. He points me in the right direction and was a key part in launching my new blog, helping me with things like custom coding, CSS styling, theme/plugin recommendations, etc. Pronaya lives in Bangladesh and his communication (and my trust in him) are 100%.
WP Johnny – he’s a busy guy but you can try hiring him and his team. I was lucky enough to have him help me remove my page builder (which I regret using in the first place and should have known better). While the work is great, it can take awhile to get things done.
WP Fix It – hired them once to improve issues related to core web vitals. While I was very happy with the work, they closed my tickets without notice saying the project was done, even when I told them I would pay more since truly fixing the issues required more work.
27. My Setup
This will cost about $500/year.
It assumes you already have a lightweight theme (i.e. GeneratePress/Kadence) and pay yearly for Rocket.net since you get 2 months free. It also assumes you’re using Rocket.net’s lower $25/mo plan (I pay $50/mo for the Business plan). For my site, this is the best setup I’ve found.
My blog costs around $800/year which is a lot cheaper than I was paying (mainly because hosting gets expensive as you scale). Scaling on Rocket.net is reasonable since monthly visits and RAM are both 10x Kinsta’s and there’s no PHP worker limits since only about 10% of traffic hits the origin (due to Ben Gabler’s Cloudflare Enterprise setup who I suggest reaching out to).
LiteSpeed is also solid and can be cheaper since LiteSpeed Cache is free and email hosting is often included. Check out NameHero, ChemiCloud, and Scala (they seem to have good specs and TrustPilot reviews). RunCloud, GridPane, and JohnnyVPS are probably best for larger sites.
Cloudways is who I was using. I still think they’re better than most hosts but it gets expensive with all the add-ons, they use Apache servers, and Cloudflare Enterprise + Breeze need work.
This is flagged when you have a short cache expiration for images, fonts, media, scripts, and stylesheets. Google fails the audit if the cache expiration is under 180 days (259200 minutes). This simply means you need to adjust your cache expiration for those files to 180 days or over.
In most cases, you will login to your hosting account and adjust the static cache expiry (or similar) to 180 days. However, this can be quite a long time that visitors won’t see an updated version of those files. If you change these files frequently, a longer cache lifespan may not be best and you may want to make it shorter (even if it’s flagged). Google warns you about this.
I’ll cover a few other ways to serve static assets with an efficient cache policy in WordPress specifically for Cloudflare, other CDNs, Google Analytics, WP Rocket, and third-party scripts.
Login to Cloudflare and go to Caching → Browser Cache TTL, then set it for “6 months.”
3. Other CDNs
Most other CDNs let you change the browser cache expiration.
For example, in BunnyCDN, go to Pullzone → Your Website → Cache → Browser Cache Expiration. In this case, there is no option for 180 days. You can either set it for 1 year or “match server cache expiration.” You’ll need to make sure your server uses the correct cache expiration.
4. WP Rocket
WP Rocket has documentation on how their browser caching works.
This code is automatically added to your .htaccess file when you activate WP Rocket. But you will notice the browser cache expiration for images, fonts, and other files is 4 months (about 2 months short of Google’s 180 day requirement). It means you’ll need to change it to 180 days.
# Expires headers (for better cache control)
ExpiresActive on
ExpiresDefault "access plus 1 month"
# cache.appcache needs re-requests in FF 3.6 (~Introducing HTML5)
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Your document html
ExpiresByType text/html "access plus 0 seconds"
# Data
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
# Feed
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/atom+xml "access plus 1 hour"
# Favicon (cannot be renamed)
ExpiresByType image/x-icon "access plus 1 week"
# Media: images, video, audio
ExpiresByType image/gif "access plus 4 months"
ExpiresByType image/png "access plus 4 months"
ExpiresByType image/jpeg "access plus 4 months"
ExpiresByType image/webp "access plus 4 months"
ExpiresByType video/ogg "access plus 4 months"
ExpiresByType audio/ogg "access plus 4 months"
ExpiresByType video/mp4 "access plus 4 months"
ExpiresByType video/webm "access plus 4 months"
# HTC files (css3pie)
ExpiresByType text/x-component "access plus 1 month"
# Webfonts
ExpiresByType font/ttf "access plus 4 months"
ExpiresByType font/otf "access plus 4 months"
ExpiresByType font/woff "access plus 4 months"
ExpiresByType font/woff2 "access plus 4 months"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
# CSS and JavaScript
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
Edit your .htaccess (you can use Htaccess File Editor if you don’t know how). Change the expiration from 4 months to 180 days. You may only want to do this for file types being flagged.
WP Rocket also suggests to check with your host to make sure they don’t block WP Rocket’s rules and that Mod_expires is enabled.
5. LiteSpeed Cache
To serve statics assets with an efficient cache policy using LiteSpeed Cache, go to LiteSpeed Cache Settings > Browser. Enable browser cache and the browser cache TTL should be left as default (31557600 seconds). If you still see errors, check if your host or CDN is overriding this.
6. W3 Total Cache
If you need to serve static assets with an efficient cache policy in W3 Total Cache, go your Browser Cache settings and change the Expires header lifetime to at least 15552000s (180 days). Make sure the cache expiration in your hosting and CDN settings aren’t overriding this.
7. Google Analytics
Google Analytics can also cause errors when serving static assets with an efficient cache policy.
If Google Analytics is appearing in PageSpeed Insights for this recommendation, CAOS Analytics lets you host analytics locally and adjust the cookie expiration period. WP Rocket’s Google Tracking Addon hosts it locally but doesn’t give you other options for the tracking code.
Install the CAOS Analytics plugin.
Go to Settings → Optimize Google Analytics → Advanced Settings → Cookie Expiry Period.
Set it to 180 days.
I recommend checking out other features in the CAOS Analytics plugin. Using a minimal analytics tracking code and serving it from your CDN can be beneficial for WordPress speed.
8. Google Fonts
Just like you hosted Google Analytics locally to control the cache lifespan, you can do the same thing with Google Fonts.
But they need to be hosted locally on your server (not pulling from fonts.gtstatic.com). You can do this by downloading your fonts directly from the Google Fonts website (remember to be minimal with font families and weights), converting them to WOFF2 format using a tool like Transfonter, then adding them to your CSS. Alternatively, you can also try the the OMGF plugin.
Once fonts are hosting locally, follow step #4 to set the cache expiration to 180 days for fonts.
9. Third-Party Scripts
Third-party code isn’t hosted on your server, so you can’t optimize it.
Google Analytics and fonts are an exception since they can be hosted locally, and therefore, you can control the cache expiration. But serving static assets with an efficient cache policy is not possible for AdSense, YouTube, Google Maps, and other third-party scripts that you might be getting errors for. Although, there may be other ways to optimize them like delaying JavaScript.
10. Purge Files And Retest
Once you’re done changing your cache expiration, remember to purge files and retest your WordPress site. Ideally you’ll have 100% for serve static assets with an efficient cache policy.
Frequently Asked Questions
How do I serve static assets with an efficient cache policy in WordPress?
Change your browser cache expiration to 180 days (or 259200 minutes). This is typically done in your hosting account, cache plugin, or CDN.
How do I serve static assets with an efficient cache policy using WP Rocket?
Edit your. htaccess file and locate the browser cache expiration code added by WP Rocket. Change the expiration from 4 months to 6 months for files flagged in Lighthouse, which are usually images or fonts.
How do I serve static assets with an efficient cache policy using Cloudflare?
Login to Cloudflare and go to Caching > Browser Cache TTL and change it to 6 months.
How do I serve static assets with an efficient cache policy using W3 Total Cache?
In your W3 Total Cache settings, go to Browser Cache and change Expires header lifetime to 180 days (15552000 seconds). Check your server and CDN to make sure they’re not overriding this setting.
Actions to Help Protect Against APT Cyber Activity:
• Enforce multifactor authentication (MFA) on all user accounts. • Implement network segmentation to separate network segments based on role and functionality. • Update software, including operating systems, applications, and firmware, on network assets. • Audit account usage.
From November 2021 through January 2022, the Cybersecurity and Infrastructure Security Agency (CISA) responded to advanced persistent threat (APT) activity on a Defense Industrial Base (DIB) Sector organization’s enterprise network. During incident response activities, CISA uncovered that likely multiple APT groups compromised the organization’s network, and some APT actors had long-term access to the environment. APT actors used an open-source toolkit called Impacket to gain their foothold within the environment and further compromise the network, and also used a custom data exfiltration tool, CovalentStealer, to steal the victim’s sensitive data.
This joint Cybersecurity Advisory (CSA) provides APT actors tactics, techniques, and procedures (TTPs) and indicators of compromise (IOCs) identified during the incident response activities by CISA and a third-party incident response organization. The CSA includes detection and mitigation actions to help organizations detect and prevent related APT activity. CISA, the Federal Bureau of Investigation (FBI), and the National Security Agency (NSA) recommend DIB sector and other critical infrastructure organizations implement the mitigations in this CSA to ensure they are managing and reducing the impact of cyber threats to their networks.
Download the PDF version of this report: pdf, 692 KB
For a downloadable copy of IOCs, see the following files:
Note: This advisory uses the MITRE ATT&CK® for Enterprise framework, version 11. See the MITRE ATT&CK Tactics and Techniques section for a table of the APT cyber activity mapped to MITRE ATT&CK for Enterprise framework.
From November 2021 through January 2022, CISA conducted an incident response engagement on a DIB Sector organization’s enterprise network. The victim organization also engaged a third-party incident response organization for assistance. During incident response activities, CISA and the trusted –third-party identified APT activity on the victim’s network.
Some APT actors gained initial access to the organization’s Microsoft Exchange Server as early as mid-January 2021. The initial access vector is unknown. Based on log analysis, the actors gathered information about the exchange environment and performed mailbox searches within a four-hour period after gaining access. In the same period, these actors used a compromised administrator account (“Admin 1”) to access the EWS Application Programming Interface (API). In early February 2021, the actors returned to the network and used Admin 1 to access EWS API again. In both instances, the actors used a virtual private network (VPN).
Four days later, the APT actors used Windows Command Shell over a three-day period to interact with the victim’s network. The actors used Command Shell to learn about the organization’s environment and to collect sensitive data, including sensitive contract-related information from shared drives, for eventual exfiltration. The actors manually collected files using the command-line tool, WinRAR. These files were split into approximately 3MB chunks located on the Microsoft Exchange server within the CU2\he\debug directory. See Appendix: Windows Command Shell Activity for additional information, including specific commands used.
During the same period, APT actors implanted Impacket, a Python toolkit for programmatically constructing and manipulating network protocols, on another system. The actors used Impacket to attempt to move laterally to another system.
In early March 2021, APT actors exploited CVE-2021-26855, CVE-2021-26857, CVE-2021-26858, and CVE-2021-27065 to install 17 China Chopper webshells on the Exchange Server. Later in March, APT actors installed HyperBro on the Exchange Server and two other systems. For more information on the HyperBro and webshell samples, see CISA MAR-10365227-2 and -3.
In April 2021, APT actors used Impacket for network exploitation activities. See the Use of Impacket section for additional information. From late July through mid-October 2021, APT actors employed a custom exfiltration tool, CovalentStealer, to exfiltrate the remaining sensitive files. See the Use of Custom Exfiltration Tool: CovalentStealer section for additional information.
APT actors maintained access through mid-January 2022, likely by relying on legitimate credentials.
Use of Impacket
CISA discovered activity indicating the use of two Impacket tools: wmiexec.py and smbexec.py. These tools use Windows Management Instrumentation (WMI) and Server Message Block (SMB) protocol, respectively, for creating a semi-interactive shell with the target device. Through the Command Shell, an Impacket user with credentials can run commands on the remote device using the Windows management protocols required to support an enterprise network.
The APT cyber actors used existing, compromised credentials with Impacket to access a higher privileged service account used by the organization’s multifunctional devices. The threat actors first used the service account to remotely access the organization’s Microsoft Exchange server via Outlook Web Access (OWA) from multiple external IP addresses; shortly afterwards, the actors assigned the Application Impersonation role to the service account by running the following PowerShell command for managing Exchange:
This command gave the service account the ability to access other users’ mailboxes.
The APT cyber actors used virtual private network (VPN) and virtual private server (VPS) providers, M247 and SurfShark, as part of their techniques to remotely access the Microsoft Exchange server. Use of these hosting providers, which serves to conceal interaction with victim networks, are common for these threat actors. According to CISA’s analysis of the victim’s Microsoft Exchange server Internet Information Services (IIS) logs, the actors used the account of a former employee to access the EWS. EWS enables access to mailbox items such as email messages, meetings, and contacts. The source IP address for these connections is mostly from the VPS hosting provider, M247.
Use of Custom Exfiltration Tool: CovalentStealer
The threat actors employed a custom exfiltration tool, CovalentStealer, to exfiltrate sensitive files.
CovalentStealer is designed to identify file shares on a system, categorize the files, and upload the files to a remote server. CovalentStealer includes two configurations that specifically target the victim’s documents using predetermined files paths and user credentials. CovalentStealer stores the collected files on a Microsoft OneDrive cloud folder, includes a configuration file to specify the types of files to collect at specified times and uses a 256-bit AES key for encryption. See CISA MAR-10365227-1 for additional technical details, including IOCs and detection signatures.
MITRE ATT&CK Tactics and Techniques
MITRE ATT&CK is a globally accessible knowledge base of adversary tactics and techniques based on real-world observations. CISA uses the ATT&CK Framework as a foundation for the development of specific threat models and methodologies. Table 1 lists the ATT&CK techniques employed by the APT actors.
Actors obtained and abused credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion. In this case, they exploited an organization’s multifunctional device domain account used to access the organization’s Microsoft Exchange server via OWA.
Actors abused PowerShell commands and scripts to map shared drives by specifying a path to one location and retrieving the items from another. See Appendix: Windows Command Shell Activity for additional information.
Command and Scripting Interpreter: Windows Command Shell
Actors abused the Windows Command Shell to learn about the organization’s environment and to collect sensitive data. See Appendix: Windows Command Shell Activity for additional information, including specific commands used.The actors used Impacket tools, which enable a user with credentials to run commands on the remote device through the Command Shell.
Actors executed malicious payloads via loading shared modules. The Windows module loader can be instructed to load DLLs from arbitrary local paths and arbitrary Universal Naming Convention (UNC) network paths.
Actors obtained and abused credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion.
Actors obtained and abused credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion. In this case, they exploited an organization’s multifunctional device domain account used to access the organization’s Microsoft Exchange server via OWA.
Actors obtained and abused credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion. In this case, they exploited an organization’s multifunctional device domain account used to access the organization’s Microsoft Exchange server via OWA.
Actors used Windows command shell commands to detect and avoid virtualization and analysis environments. See Appendix: Windows Command Shell Activity for additional information.
Actors used the taskkill command to probably disable security features. CISA was unable to determine which application was associated with the Process ID.
Actors used the systeminfo command to look for details about the network configurations and settings and determine if the system was a VMware virtual machine.The threat actor used route print to display the entries in the local IP routing table.
System Network Configuration Discovery: Internet Connection Discovery
Actors checked for internet connectivity on compromised systems. This may be performed during automated discovery and can be accomplished in numerous ways.
Actors attempted to identify the primary user, currently logged in user, set of users that commonly use a system, or whether a user is actively using the system.
Actors used the tasklist command to get information about running processes on a system and determine if the system was a VMware virtual machine.The actors used tasklist.exe and find.exe to display a list of applications and services with their PIDs for all tasks running on the computer matching the string “powers.”
Actors used the ipconfig command to get detailed information about the operating system and hardware and determine if the system was a VMware virtual machine.
Actors likely used net share command to display information about shared resources on the local computer and decide which directories to exploit, the powershell dircommand to map shared drives to a specified path and retrieve items from another, and the ntfsinfo command to search network shares on computers they have compromised to find files of interest.The actors used dir.exe to display a list of a directory’s files and subdirectories matching a certain text string.
Actors used a non-application layer protocol for communication between host and Command and Control (C2) server or among infected hosts within a network.
Actors used the certutil command with three switches to test if they could download files from the internet.The actors employed CovalentStealer to exfiltrate the files.
Actors scheduled data exfiltration to be performed only at certain times of day or at certain intervals and blend traffic patterns with normal activity.
Exfiltration Over Web Service: Exfiltration to Cloud Storage
The actor’s CovalentStealer tool stores collected files on a Microsoft OneDrive cloud folder.
DETECTION
Given the actors’ demonstrated capability to maintain persistent, long-term access in compromised enterprise environments, CISA, FBI, and NSA encourage organizations to:
Monitor logs for connections from unusual VPSs and VPNs. Examine connection logs for access from unexpected ranges, particularly from machines hosted by SurfShark and M247.
Monitor for suspicious account use (e.g., inappropriate or unauthorized use of administrator accounts, service accounts, or third-party accounts). To detect use of compromised credentials in combination with a VPS, follow the steps below:
Review logs for “impossible logins,” such as logins with changing username, user agent strings, and IP address combinations or logins where IP addresses do not align to the expected user’s geographic location.
Search for “impossible travel,” which occurs when a user logs in from multiple IP addresses that are a significant geographic distance apart (i.e., a person could not realistically travel between the geographic locations of the two IP addresses in the time between logins). Note: This detection opportunity can result in false positives if legitimate users apply VPN solutions before connecting to networks.
Search for one IP used across multiple accounts, excluding expected logins.
Take note of any M247-associated IP addresses used along with VPN providers (e.g., SurfShark). Look for successful remote logins (e.g., VPN, OWA) for IPs coming from M247- or using SurfShark-registered IP addresses.
Identify suspicious privileged account use after resetting passwords or applying user account mitigations.
Search for unusual activity in typically dormant accounts.
Search for unusual user agent strings, such as strings not typically associated with normal user activity, which may indicate bot activity.
Review the YARA rules provided in MAR-10365227-1 to assist in determining whether malicious activity has been observed.
Monitor for the installation of unauthorized software, including Remote Server Administration Tools (e.g., psexec, RdClient, VNC, and ScreenConnect).
Monitor for anomalous and known malicious command-line use. See Appendix: Windows Command Shell Activity for commands used by the actors to interact with the victim’s environment.
Monitor for unauthorized changes to user accounts (e.g., creation, permission changes, and enabling a previously disabled account).
CONTAINMENT AND REMEDIATION
Organizations affected by active or recently active threat actors in their environment can take the following initial steps to aid in eviction efforts and prevent re-entry:
Report the incident. Report the incident to U.S. Government authorities and follow your organization’s incident response plan.
Report incidents to CISA via CISA’s 24/7 Operations Center (report@cisa.gov or 888-282-0870).
For DIB incident reporting, contact the Defense Cyber Crime Center (DC3) via DIBNET at dibnet.dod.mil/portal/intranet or (410) 981 0104.
Reset all login accounts. Reset all accounts used for authentication since it is possible that the threat actors have additional stolen credentials. Password resets should also include accounts outside of Microsoft Active Directory, such as network infrastructure devices and other non-domain joined devices (e.g., IoT devices).
Monitor SIEM logs and build detections. Create signatures based on the threat actor TTPs and use these signatures to monitor security logs for any signs of threat actor re-entry.
Enforce MFA on all user accounts. Enforce phishing-resistant MFA on all accounts without exception to the greatest extent possible.
Audit accounts and permissions. Audit all accounts to ensure all unused accounts are disabled or removed and active accounts do not have excessive privileges. Monitor SIEM logs for any changes to accounts, such as permission changes or enabling a previously disabled account, as this might indicate a threat actor using these accounts.
Mitigation recommendations are usually longer-term efforts that take place before a compromise as part of risk management efforts, or after the threat actors have been evicted from the environment and the immediate response actions are complete. While some may be tailored to the TTPs used by the threat actor, recovery recommendations are largely general best practices and industry standards aimed at bolstering overall cybersecurity posture.
Segment Networks Based on Function
Implement network segmentation to separate network segments based on role and functionality. Proper network segmentation significantly reduces the ability for ransomware and other threat actor lateral movement by controlling traffic flows between—and access to—various subnetworks. (See CISA’s Infographic on Layering Network Security Through Segmentation and NSA’s Segment Networks and Deploy Application-Aware Defenses.)
Isolate similar systems and implement micro-segmentation with granular access and policy restrictions to modernize cybersecurity and adopt Zero Trust (ZT) principles for both network perimeter and internal devices. Logical and physical segmentation are critical to limiting and preventing lateral movement, privilege escalation, and exfiltration.
Manage Vulnerabilities and Configurations
Update software, including operating systems, applications, and firmware, on network assets. Prioritize patching known exploited vulnerabilities and critical and high vulnerabilities that allow for remote code execution or denial-of-service on internet-facing equipment.
Implement a configuration change control process that securely creates device configuration backups to detect unauthorized modifications. When a configuration change is needed, document the change, and include the authorization, purpose, and mission justification. Periodically verify that modifications have not been applied by comparing current device configurations with the most recent backups. If suspicious changes are observed, verify the change was authorized.
Search for Anomalous Behavior
Use cybersecurity visibility and analytics tools to improve detection of anomalous behavior and enable dynamic changes to policy and other response actions. Visibility tools include network monitoring tools and host-based logs and monitoring tools, such as an endpoint detection and response (EDR) tool. EDR tools are particularly useful for detecting lateral connections as they have insight into common and uncommon network connections for each host.
Monitor the use of scripting languages (e.g., Python, Powershell) by authorized and unauthorized users. Anomalous use by either group may be indicative of malicious activity, intentional or otherwise.
Restrict and Secure Use of Remote Admin Tools
Limit the number of remote access tools as well as who and what can be accessed using them. Reducing the number of remote admin tools and their allowed access will increase visibility of unauthorized use of these tools.
Use encrypted services to protect network communications and disable all clear text administration services(e.g., Telnet, HTTP, FTP, SNMP 1/2c). This ensures that sensitive information cannot be easily obtained by a threat actor capturing network traffic.
Implement a Mandatory Access Control Model
Implement stringent access controls to sensitive data and resources. Access should be restricted to those users who require access and to the minimal level of access needed.
Audit Account Usage
Monitor VPN logins to look for suspicious access (e.g., logins from unusual geo locations, remote logins from accounts not normally used for remote access, concurrent logins for the same account from different locations, unusual times of the day).
Closely monitor the use of administrative accounts. Admin accounts should be used sparingly and only when necessary, such as installing new software or patches. Any use of admin accounts should be reviewed to determine if the activity is legitimate.
Ensure standard user accounts do not have elevated privileges Any attempt to increase permissions on standard user accounts should be investigated as a potential compromise.
VALIDATE SECURITY CONTROLS
In addition to applying mitigations, CISA, FBI, and NSA recommend exercising, testing, and validating your organization’s security program against threat behaviors mapped to the MITRE ATT&CK for Enterprise framework in this advisory. CISA, FBI, and NSA recommend testing your existing security controls inventory to assess how they perform against the ATT&CK techniques described in this advisory.
To get started:
Select an ATT&CK technique described in this advisory (see Table 1).
Align your security technologies against the technique.
Test your technologies against the technique.
Analyze the performance of your detection and prevention technologies.
Repeat the process for all security technologies to obtain a set of comprehensive performance data.
Tune your security program, including people, processes, and technologies, based on the data generated by this process.
CISA, FBI, and NSA recommend continually testing your security program, at scale, in a production environment to ensure optimal performance against the MITRE ATT&CK techniques identified in this advisory.
RESOURCES
CISA offers several no-cost scanning and testing services to help organizations reduce their exposure to threats by taking a proactive approach to mitigating attack vectors. See cisa.gov/cyber-hygiene-services.
U.S. DIB sector organizations may consider signing up for the NSA Cybersecurity Collaboration Center’s DIB Cybersecurity Service Offerings, including Protective Domain Name System (PDNS) services, vulnerability scanning, and threat intelligence collaboration for eligible organizations. For more information on how to enroll in these services, email dib_defense@cyber.nsa.gov.
ACKNOWLEDGEMENTS
CISA, FBI, and NSA acknowledge Mandiant for its contributions to this CSA.
APPENDIX: WINDOWS COMMAND SHELL ACTIVITY
Over a three-day period in February 2021, APT cyber actors used Windows Command Shell to interact with the victim’s environment. When interacting with the victim’s system and executing commands, the threat actors used /q and /c parameters to turn the echo off, carry out the command specified by a string, and stop its execution once completed.
On the first day, the threat actors consecutively executed many commands within the Windows Command Shell to learn about the organization’s environment and to collect sensitive data for eventual exfiltration (see Table 2).
Command
Description / Use
net share
Used to create, configure, and delete network shares from the command-line.[1] The threat actor likely used this command to display information about shared resources on the local computer and decide which directories to exploit.
powershell dir
An alias (shorthand) for the PowerShell Get-ChildItem cmdlet. This command maps shared drives by specifying a path to one location and retrieving the items from another.[2] The threat actor added additional switches (aka options, parameters, or flags) to form a “one liner,” an expression to describe commonly used commands used in exploitation: powershell dir -recurse -path e:\<redacted>|select fullname,length|export-csv c:\windows\temp\temp.txt. This particular command lists subdirectories of the target environment when.
systeminfo
Displays detailed configuration information [3], tasklist – lists currently running processes [4], and ipconfig – displays all current Transmission Control Protocol (TCP)/IP network configuration values and refreshes Dynamic Host Configuration Protocol (DHCP) and Domain Name System (DNS) settings, respectively [5]. The threat actor used these commands with specific switches to determine if the system was a VMware virtual machine: systeminfo > vmware & date /T, tasklist /v > vmware & date /T, and ipconfig /all >> vmware & date /.
route print
Used to display and modify the entries in the local IP routing table. [6] The threat actor used this command to display the entries in the local IP routing table.
netstat
Used to display active TCP connections, ports on which the computer is listening, Ethernet statistics, the IP routing table, IPv4 statistics, and IPv6 statistics.[7] The threat actor used this command with three switches to display TCP connections, prevent hostname determination of foreign IP addresses, and specify the protocol for TCP: netstat -anp tcp.
certutil
Used to dump and display certification authority (CA) configuration information, configure Certificate Services, backup and restore CA components, and verify certificates, key pairs, and certificate chains.[8] The threat actor used this command with three switches to test if they could download files from the internet: certutil -urlcache -split -f https://microsoft.com temp.html.
ping
Sends Internet Control Message Protocol (ICMP) echoes to verify connectivity to another TCP/IP computer.[9] The threat actor used ping -n 2 apple.com to either test their internet connection or to detect and avoid virtualization and analysis environments or network restrictions.
taskkill
Used to end tasks or processes.[10] The threat actor used taskkill /F /PID 8952 to probably disable security features. CISA was unable to determine what this process was as the process identifier (PID) numbers are dynamic.
PowerShell Compress-Archive cmdlet
Used to create a compressed archive or to zip files from specified files and directories.[11] The threat actor used parameters indicating shared drives as file and folder sources and the destination archive as zipped files. Specifically, they collected sensitive contract-related information from the shared drives.
On the second day, the APT cyber actors executed the commands in Table 3 to perform discovery as well as collect and archive data.
Command
Description / Use
ntfsinfo.exe
Used to obtain volume information from the New Technology File System (NTFS) and to print it along with a directory dump of NTFS meta-data files.[12]
WinRAR.exe
Used to compress files and subsequently masqueraded WinRAR.exe by renaming it VMware.exe.[13]
On the third day, the APT cyber actors returned to the organization’s network and executed the commands in Table 4.
Command
Description / Use
powershell -ep bypass import-module .\vmware.ps1;export-mft -volume e
Threat actors ran a PowerShell command with parameters to change the execution mode and bypass the Execution Policy to run the script from PowerShell and add a module to the current section: powershell -ep bypass import-module .\vmware.ps1;export-mft -volume e. This module appears to acquire and export the Master File Table (MFT) for volume E for further analysis by the cyber actor.[14]
set.exe
Used to display the current environment variable settings.[15] (An environment variable is a dynamic value pointing to system or user environments (folders) of the system. System environment variables are defined by the system and used globally by all users, while user environment variables are only used by the user who declared that variable and they override the system environment variables (even if the variables are named the same).
dir.exe
Used to display a list of a directory’s files and subdirectories matching the eagx* text string, likely to confirm the existence of such file.
tasklist.exe and find.exe
Used to display a list of applications and services with their PIDs for all tasks running on the computer matching the string “powers”.[16][17][18]
ping.exe
Used to send two ICMP echos to amazon.com. This could have been to detect or avoid virtualization and analysis environments, circumvent network restrictions, or test their internet connection.[19]
del.exe with the /f parameter
Used to force the deletion of read-only files with the *.rar and tempg* wildcards.[20]
This article describes how to use your UniFi Talk devices once they’re set up and configured in the Talk application. For more information on how to set up and configure your devices, please refer to these articles on adopting devices and using the Talk application.
For optimal performance, make sure you’re using the latest firmware for your devices and the latest UniFi Talk application version.
To configure voicemail on the Touch and Touch Max phone:
From the Keypad, dial *86 or long-press 1 to access voicemail configuration.
Follow the audio prompts to complete voicemail configuration.
Note: Visual voicemail configuration is coming soon.
To configure voicemail on the Flex phone:
Press the MESSAGE button to access voicemail configuration.
Follow the audio prompts to complete voicemail configuration.
Forward an incoming call
To forward an incoming call on the Touch and Touch Max phone:
From the incoming call screen, press the blue Forward button to view your contact list.
Select a contact to forward the incoming call.
Start a parallel call
To start a parallel call (i.e., start a new call while one or more calls are already ongoing) on the Touch and Touch Max phone:
From the active call screen, press the Add / Transfer button.
There are two options for starting a parallel call:
From the Contacts tab of the Add / Transfer screen, select a contact from your contact list.
From the Keypad tab of the Add / Transfer screen, dial a number and press the green button at the bottom of the screen.
Press the Call button to start a parallel call. The current active call will be placed on hold.
When two or more calls are active in parallel, swipe left or right to navigate between active calls.
Transfer an active call
To transfer an active call on the Touch or Touch Max phone:
From the active call screen, press the Add / Transfer button.
There are two options for transferring an active call:
From the Contacts tab of the Add / Transfer screen, select a contact from your contact list.
From the Keypad tab of the Add / Transfer screen, dial a number and press the green button at the bottom of the screen.
You will have the option to press Transfer or Warm Transfer.
If you press the Transfer button, this will utilize a cold (blind) transfer. The active call will immediately be transferred and will ring the destination phone once you press the Transfer button.
If you select the Warm Transfer option, the original caller is placed on hold while the transfer destination is dialed. The transfer destination has to pick up, at which point you have to again press the blue transfer button to complete the transfer.
To transfer an active call on the Flex phone:
While the call is active, press the TRANSFER button.
From here, you can either transfer to a specific number or a contact.
To transfer to a specific number, enter the number you’d like to transfer the call to and press the DIAL soft key.
To transfer to a contact, press the CONTACT soft key to load your contact list. Navigate the contact list using the up/down keys and dial the desired contact by pressing the DIAL soft key or the OK button.
You’re now calling the transfer destination. Once the transfer destination answers the call, press the TRANSFER button again to connect the original caller with the transfer destination.
Note: The Flex phone utilizes a warm (attended) transfer. The original caller will be placed on hold while a second call is established with the transfer destination. Once the second call is connected, the transfer can be completed to connect the original caller with the transfer destination.
Start a conference call
To start a conference call on the Touch and Touch Max phone:
From the active call screen, press the Add / Transfer button.
There are two options for adding additional parties to a conference call:
From the Contacts tab of the Add / Transfer screen, select a contact and press the Add to Call button.
From the Keypad tab of the Add / Transfer screen, dial the additional party’s number, press the green button at the bottom of the screen, and select the Add to Call option.
To start a three-way conference call on the Flex phone:
While the call is active, press the CONF soft key.
From here, you can either start a call with a specific number or a contact.
To call a specific number, enter the number you’d like to transfer the call to and press the DIAL soft key.
To call a contact, press the CONTACT soft key to load your contact list. Navigate the contact list using the up/down keys and dial the desired contact by pressing the DIAL soft key or the OK button.
You’re now calling the third party. Once the third party answers the call, press the CONF soft key again to start a conference call.
Manage your status
To manage your status on the Touch and Touch Max phone:
Press the App Selector button, located below the phone’s touchscreen to the left of the Ubiquiti logo.
Select Settings and click on My Status.
From here, you can select between three status settings:
Create a DND Allow List to allow specific numbers to ring your device when your status is set to Do Not Disturb.
Specify a redirect number using the Change Redirect Number button on the My Status page.
Available: Incoming calls will ring your device.
Do Not Disturb (DND): Incoming calls will be sent to voicemail.
Redirect: Incoming calls will be forwarded to the specified redirect number.
To manage your status on the Flex phone:
Do Not Disturb (DND): Incoming calls will be sent to voicemail.
Press the DND soft key to place your device in Do Not Disturb mode. Incoming calls will go to voicemail. When DND is enabled you will see the word DND with a symbol in the top-left corner of the screen.
Press the DND soft key again to disable Do Not Disturb mode.
Redirect: Incoming calls will be forwarded to the specified redirect number.
Press the MENU soft key, then select 2. SETTINGS.
Use the up/down keys to navigate the settings menu and select 5. CALL FORWARD.
Press the YES soft key to set a redirect status.
On the CALL FORWARD NUMBER screen, press the EDIT soft key, enter your redirect number with the keypad, and press the CONFIRM soft key.
Troubleshooting
My Talk device is showing a Connection Error screen
This error means that your Talk device cannot communicate with the Talk application.
To troubleshoot a Connection Error state:
Ensure that the Talk application is running. To check on Talk’s status, open unifi.ui.com, select your UniFi OS Console, go to Settings> Updates, and locate the Talk application tile. If Talk is stopped, click on the three dots menu in the Talk application tile and select Start.
Restart the Talk application. See this section for instructions on how to restart Talk.
Restart your UniFi OS Console by going to its Settings > Advanced and clicking Restart Console under the Console Controls header. If you’re still encountering this issue after the troubleshooting steps above, please contact Ubiquiti Support.
To create new users in the UniFi Talk application:
Open the Users tab and click the Add User button in the top-right corner of the screen.
Type the user’s first name, last name, and extension in the respective text fields. If you do not assign an extension, the UniFi Talk application will do so automatically.
Select the user’s phone number from the drop-down menu and click Save. If no phone number is selected, the user will only be able to make internal calls unless they are added to a group with a number assigned.
Assign phones to users
A user must be assigned to each phone managed by the UniFi Talk application. You can assign a phone to a user on the Devices page or in the user’s profile panel.
To assign a phone to a user on the Devices page:
Click the Devices icon in the left navigation bar.
Hover your cursor over the phone you’d like to assign to the user, then click the Assign link when it appears.
Select the user from the pop-up window’s drop-down field, then click Assign.
To assign a phone to a user via their profile panel:
Click the Users icon in the left navigation bar.
Click the user that you’d like to assign a phone to.
Click the Manage tab, then scroll down and click the Manage drop-down option.
Select the phone that you’d like to assign to the user from the Reassign Device drop-down field.
Click the user that you’d like to assign a number to.
Click the Manage tab, then scroll down and click the Manage drop-down option.
Select the number that you’d like to assign to the user from the Change Number drop-down field.
Click Save at the bottom of the panel.
Note: Users without a number assigned will not be able to make or receive external calls, but will still have an active extension that can make and receive unlimited internal calls.
Add a third-party SIP provider
Session Initiation Protocol (SIP) providers facilitate real-time video and voice communication (e.g., Twilio, Voxbone, 3CX, etc.). If you currently subscribe to a third-party SIP provider, you don’t have to purchase a UniFi Talk subscription to use your existing service in the UniFi Talk application.
To add a third-party SIP provider to your UniFi Talk application:
Create and configure a new trunk in your SIP provider’s settings console:
Create a credential list and assign username and password credentials to the trunk itself.
Add an ACL IP and a new entry for your router’s public IP address (e.g., 1.2.3.4/32).
Add an origination uri in the same format as your router’s public IP address (e.g., sip:1.2.3.4:6767).
Ensure that the Direct Inward Dialing (DID) number(s) you want to use with UniFi Talk are assigned to the newly created trunk.
Add your SIP provider’s information to the UniFi Talk application:
Go to Settings > System Settings.
Click the Add Third-Party SIP Provider button at the bottom of the screen.
Enter your provider’s name.
Enter your SIP provider’s required fields:
Locate your SIP provider’s custom fields by referencing either the Providers ITSPs directory or your provider’s user documentation.
Click the Add Field button in the UniFi Talk Settings menu.
Type or paste the copied field into the Add Fields window and click the + icon. Repeat this process for multiple entries.
Click Done once all fields have been added.
Type the DID number(s) from your SIP provider in the Input Numbers field(s) in either E.164 format (e.g., +10123456789) or the format supported by your provider.
Add your SIP provider’s media and signaling servers:
Click the Add IP Address Range button.
Type the address information in the corresponding fields and click Add.
Enable the Static Signaling Port toggle located in the Network tab of the UniFi Talk Settings menu.
Assign the new DID number(s) and phone(s) to users registered in your UniFi Talk application:
Open the Users page of your UniFi Talk application.
Click the desired user then click the Manage tab at the top of their profile panel.
Select the phone that you’d like to assign the user from the Reassign Device drop-down menu.
Select the DID number that you’d like to assign the user from the Change Number drop-down menu.
Repeat this process as needed for additional users.
Note: If you’re using a third-party SIP provider, said provider will be responsible for maintaining E911 compliance. Please contact your provider for more guidance on how to ensure that all requirements are met.
Add or adjust port forwarding rule(s) for the UniFi OS Console hosting the UniFi Talk application:
Open the UniFi Network Settings menu and click the Firewall & Security tab.
Locate the Port Forwarding section and click the Create New Forwarding Rule button.
Add all required information to apply the port forwarding rule(s) to your UniFi OS Console.
If you have another router upstream from your UniFi OS Console, forward incoming traffic to Port 6767 of your UniFi OS Console.
Set up a Smart Attendant
The Smart Attendant helps you create and execute custom call routing to ensure that all your calls are directed to the right extension or preferred language speaker.
To set up a Smart Attendant:
Open the Smart Attendant tab in the UniFi Talk application. If you already have one or more Smart Attendants, click the Add New button. Otherwise, proceed with setup.
Name your Smart Attendant and click Next.
Select the number(s) you want the Smart Attendant to answer from the drop-down field.
If you select None, your Smart Attendant will not be active until you assign it a number.
You can also select multiple numbers for your Smart Attendant to answer.
From this screen, you can also configure the Ringback and Hold Music that your Smart Attendant will use.
Ringback: The audio that callers hear when dialing a Talk user or group via your Smart Attendant.
Hold Music: The audio that callers hear when a Talk user places them on hold after being dialed via your Smart Attendant.
Select if your Smart Attendant will behave differently based on business hours. When enabled, you can define custom call handling for business hours and non-business hours.
If you select Yes, configure your business hours schedule. You can add multiple business hour segments within a single day.
Select if you wish to have extension dialing enabled. When enabled, callers can dial an extension to connect with a user or group without going through Smart Attendant menus.
If you select Yes, select an extension dialing method:
All Users and Groups: All users and groups in your Talk application can be dialed by their extension.
Custom List: Only the Talk users and groups added to the custom list can be dialed by their extension.
Smart Attendant Ring Menus: Only the Talk users and groups added to the Smart Attendant with a Ring Phone(s) menu can be dialed by their extension.
Configure your Smart Attendant’s greeting message:
Select the voice your Smart Attendant will use for generated audio.
Select the greeting type. You can generate audio from text or use custom audio by recording or uploading a file.
Following the instructions to configure your greeting based on the type selected.
Create your call routing tree:
Enter the prompt message and select the user(s) and/or group(s) that each key press will direct to.
If you don’t need a call routing tree or wish to configure this later, click No then Finish.
To add a new menu or user:
Hover your cursor over the menu that you’d like to add a new block to and click the + icon when it appears.
Choose between the two different types of blocks:
Keypress Prompt (e.g., Press 1 for Sales)
Ring Phone(s) (Dial a specific user or group)
Play Audio (Play an audio message)
Voicemail (Leave voicemail for a specific user)
Keypress to Return (Return to the previous menu)
Schedule (Configure call handling based on a schedule)
To delete a menu or user, hover your cursor over it and click the X icon when it appears.
Manage voicemails and call recordings
The UniFi Talk application collects voicemail by default. To listen to voicemails, click the Voicemail button on your Talk phone.
To automate call recordings:
Enable the Automatic Call Recording toggle from Settings > Call Settings.
Review the disclaimer text in the pop-up advisory window carefully, and click I Understand if you consent.
To disable voicemail:
Open the Settings menu and click the Call Settings tab.
Open the Voicemail drop-down.
Disable the voicemail toggle.
View call logs
To view your call logs:
Open the Call Log tab to view a listing of every call made with a device managed by the UniFi Talk application.
View the details of a specific call:
Click the desired call’s entry or hover your cursor over its listing and click the View link when it appears.
Review basic call information (e.g., caller, recipient, call experience score, length, date, and time) from the General section of the call log’s pop-up panel.
Click the Recording tab at the top of the call log’s panel to listen to its recording.
For voicemail messages, click the Voicemail tab at the top of the call log’s panel to listen to its recording.
To delete a call log, hover your cursor over the log’s entry and click Delete, then click the Delete button in the confirmation pop-up window.
Set up groups
The UniFi Talk application allows you to create groups that allow multiple phones to share the same number and ring. Groups can utilize all UniFi Talk application features, including the Smart Attendant.
To create a new group:
Click the Groups icon in the left navigation bar and click the Create New Group link in the top-right corner of the following page.
Enter a group name, assign a number to the group (optional), and add an internal extension (optional).
Select either Simultaneous or Sequential call handling.
Simultaneous: When the group is called, all phones assigned to group members will ring. The first phone to answer will receive the call and the other phones will stop ringing.
Sequential: When the group is called, phones assigned to group members will ring in the order you define.
Manage the group’s members. You can add Talk users and global contacts to a group.
Configure the Ringback for the group. This is the audio that callers hear when calling the group.
Click Create.
Note: Groups without a number assigned will not be able to make or receive external calls, but will still have an active extension that can make and receive unlimited internal calls.
To assign a specific outgoing number to a user who is a member of several groups:
Open the Users page, select the user, and click the Manage tab.
Select the desired outgoing number from the drop-down field.
Troubleshooting
I can’t receive incoming calls
We recommend enabling the static signaling port feature if your UniFi Talk deployment can’t receive incoming calls. The instructions below describe how to implement this fix.
In the Talk application, enable the toggle for static signaling port within Settings > System Settings > Create Static Signaling Port.
Create a port forwarding rule that forwards port 6767 to your UniFi OS Console running the Talk application. If your routing tasks are being handled by UniFi, go to the Network application to create this rule within Settings > Advanced Features > Advanced Gateway Settings > Port Forwarding. Need help creating this port forwarding rule?
Try making a call to one of your UniFi Talk phones from an external number to test if incoming calling is working.
If the steps above did not work, try creating a firewall rule that allows Internet traffic destined for port 6767 of your UniFi OS Console running the Talk application. If your firewall rules are managed by UniFi, go to the Network application to create this rule within Settings > Traffic & Security > Global Threat Management > Firewall.Need help creating this rule?
I can’t make outgoing calls
For outgoing call failures, we recommend disabling the SIP ALG setting found in the router upstream from the UniFi OS Console running the Talk application (e.g., the router modem installed by your ISP). The SIP ALG setting is sometimes enabled by default on these devices and interferes with telephony.
I could previously make and/or receive calls, and now I can’t
In some cases, events like a network outage can result in degraded Talk application performance. This can be resolved by restarting the Talk application.
To restart the Talk application:
From unifi.ui.com, select your UniFi OS Console, go to Settings> Updates, and locate the Talk application tile.
Click on the three dots menu in the Talk application tile and select Stop.
After the Talk application has stopped, click on the Start Talk button.
If you need to factory reset, replace, or migrate to a new UniFi OS Console, or reset the Talk application, you can recover your Talk subscriptions and phone numbers during the UniFi Talk setup process. This option is available when you’re logged in using the same Ubiquiti account that manages your Talk subscriptions.
To recover or migrate your Talk subscriptions:
Log in to your Ubiquiti account at unifi.ui.com and select the UniFi OS Console you’d like to recover or migrate your Talk subscriptions to.
Launch the UniFi Talk Setup Wizard.
If you have multiple UniFi Talk deployments associated with your Ubiquiti account, you’ll see a list of previous deployments to select from. Hover over the information tooltip to view the phone numbers associated with each deployment.
Select the deployment with the phone numbers that you want to recover or migrate.
Click the Next button to continue setup.
On the Setup Device(s) page, you’ll now have the option to assign your recovered or migrated phone numbers to users and devices. These are available for selection from the Number / Area Code dropdown menu. Make your selections and click Next.
Complete the UniFi Talk setup process to finish recovering or migrating your Talk subscriptions and phone numbers.
Notes: A Talk subscription can only be active on a single UniFi OS Console. If you use this option during the UniFi Talk setup process while a subscription is still active on another UniFi OS Console, your subscription(s) will be transferred and will no longer be accessible from that device.
You can configure UniFi Protect location-based activity notifications so you are only notified when the user(s) are off-site. This article outlines the steps needed to set this up for your account.
In the UniFi OS settings, go to Console Settings > Time Zone / Location>Edit Location on Map.
Search for the Address or drag your UOS Console to the correct location.
Adjust the Geofencing Radius slider to define your console’s on-site radius (i.e, “geofence”).
Click Apply Changes when you’ve set the desired geofence.
If you experience unexpected status changes while on site, increase the geofence’s radius.
Configure your primary mobile device
Your primary mobile device will be the one used to determine whether you are on or off-site (i.e., within the geofence).
To configure your primary mobile device:
Make sure cellular data is enabled on your mobile device.
Make sure that the UniFi Protect mobile app has proper location permissions:
For iOS devices, set the Protect mobile app’s Location Setting permission to Always. Precise Location should also be enabled.
For Android devices, make sure that Protect mobile app’s location access is set to Allow all the time.
Open the Protect mobile app, tap the Settings icon on the bottom-left corner of the screen followed by Primary Device; then, select the desired mobile device from the list.
To activate your UniFi OS Console’s geofence, use the Protect mobile app to go to Settings > UniFi OS Console > Network and enable the Geofencing toggle.
Configure location-based activity notifications
After you’ve configured the locations of your UniFi OS Console and primary mobile device, you can create activity notifications using your UniFi Protect web application or mobile app.
To create activity notifications using the UniFi Protect mobile app:
Go to Settings > Notificationsto create a new activity notification or edit an existing one.
Select from Off, Default, or Custom.
If you choose Custom, click the Activity tab to customize the notification for each camera.
To create or edit activity notifications using the Protect web application:
Log in and go to Settings > Notifications > Activity.
Adjust When to Send> Location Based to receive notifications when you are off site (When I’m Away) or when all users are off site (When Everyone is Away).
Go back and customize the notifications for your cameras.
Troubleshooting inaccurate location tracking
The Protect mobile app uses GPS and communication with the UniFi OS Console to provide an accurate location.
If you are experiencing location inaccuracies, follow the device-specific steps below to improve the mobile app’s location tracking:
For iOS / iPadOS devices:
Disable Low Power mode, as it may prevent the app from sending location status updates.
Enable Background App Refresh and Cellular Data for the UniFi Protect mobile app.
Disable VPN or Mobile Hotspot if they interfere with location accuracy.
For Android devices:
Select High Accuracy mode for mobile phone location tracking, if available.
Disable data saving settings.
Disable battery optimization for the UniFi Protect mobile app by tapping Settings > Battery > Battery Optimization > Don’t Optimize.
Disable power saving mode to ensure it isn’t auto-enabled once your phone battery is low.
If your mobile has a Deep Sleep feature, disable it for the UniFi Protect mobile app to make sure you don’t receive location status updates after opening it.