{"id":380459,"date":"2026-10-05T21:01:48","date_gmt":"2026-10-05T21:01:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/bypass-guard-for-cloudflare\/"},"modified":"2026-10-05T21:01:35","modified_gmt":"2026-10-05T21:01:35","slug":"bypass-guard-for-cloudflare","status":"publish","type":"plugin","link":"https:\/\/as.wordpress.org\/plugins\/bypass-guard-for-cloudflare\/","author":21116441,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1.2","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"Bypass Guard for Cloudflare","header_author":"Gabor Angyal","header_description":"Blocks requests that bypass Cloudflare by requiring a secret token header. For hosts that offer no stronger origin protection.","assets_banners_color":"","last_updated":"2026-10-05 21:01:35","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/agabor\/bypass-guard-for-cloudflare","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":201,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"gaborangyal","date":"2026-10-05 21:01:35","revision":3729653}},"upgrade_notice":{"1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[3882,1174,1431,16709,600],"plugin_category":[54],"plugin_contributors":[251009],"plugin_business_model":[],"class_list":["post-380459","plugin","type-plugin","status-publish","hentry","plugin_tags-cloudflare","plugin_tags-firewall","plugin_tags-header","plugin_tags-origin","plugin_tags-security","plugin_category-security-and-spam-protection","plugin_contributors-gaborangyal","plugin_committers-gaborangyal"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/bypass-guard-for-cloudflare.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>The problem<\/strong><\/p>\n\n<p>Cloudflare protects your site only for traffic that goes through Cloudflare. If your server's IP address leaks, attackers can send requests to it directly and skip Cloudflare's protection entirely. The usual fixes require server or firewall access, which shared hosting providers often don't give you.<\/p>\n\n<p><strong>The solution<\/strong><\/p>\n\n<p>Bypass Guard uses a shared secret to tell proxied traffic from direct traffic:<\/p>\n\n<ol>\n<li>The plugin generates a random secret token.<\/li>\n<li>You add a rule in Cloudflare that attaches this token to every request it forwards, in a header called <code>BYPASS-GUARD-TOKEN<\/code>.<\/li>\n<li>The plugin checks each WordPress request. If the header is missing or wrong, the request is answered with <code>403 Forbidden<\/code>.<\/li>\n<\/ol>\n\n<p>Because the header is added at Cloudflare's edge, a request that hits the origin directly arrives without it, unless the sender already knows the token.<\/p>\n\n<p><strong>Built-in safety against locking yourself out<\/strong><\/p>\n\n<ul>\n<li>The filter cannot be switched on until the plugin has seen at least one request carrying the correct token. This proves your Cloudflare rule works before anything gets blocked.<\/li>\n<li>Until then, the settings page shows a step by step setup guide with copy buttons for the header name and token.<\/li>\n<li>WP-CLI commands are never filtered, so you always keep command line access.<\/li>\n<li>Deactivating the plugin always switches the filter off.<\/li>\n<\/ul>\n\n<p><strong>Logging<\/strong><\/p>\n\n<p>Every blocked request is logged with its date and time, IP address, request method, URL and user agent. You can view and clear the log on the settings page. This helps you confirm that the filter works, spot scanners that found your server's IP, and find legitimate services that were blocked by mistake.<\/p>\n\n<p>The log keeps the 500 most recent entries, so a flood of requests cannot fill your database. Token values are never logged, not even incorrect ones.<\/p>\n\n<p>The logged IP address is the one that actually connected to your server. Headers such as <code>CF-Connecting-IP<\/code> or <code>X-Forwarded-For<\/code> are ignored for blocked requests, because anyone bypassing Cloudflare can set them to any value.<\/p>\n\n<p><strong>Is this plugin right for you?<\/strong><\/p>\n\n<p>This plugin is a fallback for when better options are not available. Check with your host whether you can use either of these first:<\/p>\n\n<ul>\n<li><strong>Authenticated Origin Pulls<\/strong> (mutual TLS): your web server only accepts connections that present Cloudflare's client certificate.<\/li>\n<li><strong>A firewall that only allows Cloudflare's IP ranges<\/strong>: your server refuses connections from anywhere else.<\/li>\n<\/ul>\n\n<p>Both work at the server or network level, protect everything (including images and cached pages) and do not depend on a shared secret. Many shared hosting plans allow neither, and that is the situation this plugin is built for. You can also use it alongside them as an extra layer.<\/p>\n\n<p><strong>Limitations<\/strong><\/p>\n\n<p>The plugin runs inside WordPress, so it only sees requests that WordPress itself handles:<\/p>\n\n<ul>\n<li><strong>Static files<\/strong> (images, CSS, JavaScript, uploads) are usually served directly by the web server and stay reachable.<\/li>\n<li><strong>Page caches that run before plugins load<\/strong> are not filtered. This includes caching plugins using an <code>advanced-cache.php<\/code> drop-in and server-level caches such as LiteSpeed Cache, Varnish or nginx FastCGI cache. Cached pages may still be served to direct requests.<\/li>\n<li><strong>The token is a shared secret.<\/strong> Anyone who learns it can get past the filter. It is visible to site administrators, to anyone with database access and to anyone with access to your Cloudflare account.<\/li>\n<\/ul>\n\n<p>If you can edit your server configuration or <code>.htaccess<\/code> file, checking the same header there as well closes the first two gaps.<\/p>\n\n<p><strong>Source code and contributions<\/strong><\/p>\n\n<p>Bypass Guard for Cloudflare is developed openly on GitHub. Bug reports, feature requests and pull requests are welcome:<\/p>\n\n<p>https:\/\/github.com\/agabor\/bypass-guard-for-cloudflare<\/p>\n\n<p><strong>Disclaimer<\/strong><\/p>\n\n<p>Bypass Guard for Cloudflare is an independent open source project. It is not affiliated with, endorsed by or supported by Cloudflare, Inc. \"Cloudflare\" is a trademark of Cloudflare, Inc. and is used here only to describe the service this plugin works with. No Cloudflare logos, artwork or documentation are included in this plugin.<\/p>\n\n<!--section=installation-->\n<p><strong>Before you start<\/strong><\/p>\n\n<p>Make sure that:<\/p>\n\n<ul>\n<li>Your site's DNS records are <strong>proxied<\/strong> in Cloudflare (orange cloud icon). DNS-only records send traffic straight to your server, so the header would never be added.<\/li>\n<li>Your SSL\/TLS encryption mode is <strong>Full (strict)<\/strong>. In Flexible mode Cloudflare talks to your server over plain HTTP, which would send the token unencrypted with every request.<\/li>\n<li>You have FTP, SFTP, file manager or WP-CLI access to your site, in case you need to disable the plugin manually (see the FAQ).<\/li>\n<\/ul>\n\n<p><strong>Step 1: Install the plugin<\/strong><\/p>\n\n<p>Install and activate it from the Plugins screen, or upload the <code>bypass-guard-for-cloudflare<\/code> folder to <code>\/wp-content\/plugins\/<\/code> and activate it. Then open <strong>Settings \u2192 Bypass Guard<\/strong>. You will see the header name and your generated token, each with a Copy button.<\/p>\n\n<p><strong>Step 2: Add the header in Cloudflare<\/strong><\/p>\n\n<p>Create a Request Header Transform Rule for your site that sets a static header on all incoming requests:<\/p>\n\n<ul>\n<li>Header name: <code>BYPASS-GUARD-TOKEN<\/code><\/li>\n<li>Value: the token from the settings page<\/li>\n<\/ul>\n\n<p>At the time of writing, you find this in the Cloudflare dashboard by opening your site (zone), going to <strong>Rules \u2192 Overview<\/strong> and choosing <strong>Create rule \u2192 Request Header Transform Rule<\/strong>. Give the rule any name, set the match condition to <strong>All incoming requests<\/strong>, choose <strong>Set static<\/strong> under the header modification, fill in the two values above and select <strong>Deploy<\/strong>. Cloudflare occasionally reorganises its dashboard; if these menu names do not match, look for \"Transform Rules\" in Cloudflare's own documentation.<\/p>\n\n<p><strong>Step 3: Confirm detection<\/strong><\/p>\n\n<p>Reload the plugin's settings page through your normal domain. Once a request with the correct token arrives, the Header Status changes to <strong>Detected<\/strong> and the <strong>Enable Filter<\/strong> button becomes available.<\/p>\n\n<p><strong>Step 4: Enable the filter and test it<\/strong><\/p>\n\n<p>Select <strong>Enable Filter<\/strong>. Then check that direct access is blocked by sending a request straight to your server's IP address. For example, from a terminal:<\/p>\n\n<pre><code>curl -k -I --resolve example.com:443:203.0.113.10 https:\/\/example.com\/\n<\/code><\/pre>\n\n<p>Replace <code>example.com<\/code> with your domain and <code>203.0.113.10<\/code> with your server's real IP. The response should be <code>403 Forbidden<\/code>, and the request should appear in the plugin's log.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"is%20this%20plugin%20made%20by%20cloudflare%3F\"><h3>Is this plugin made by Cloudflare?<\/h3><\/dt>\n<dd><p>No. It is an independent open source plugin with no connection to Cloudflare, Inc. Please do not contact Cloudflare support about it; use the GitHub issue tracker instead.<\/p><\/dd>\n<dt id=\"i%20locked%20myself%20out.%20how%20do%20i%20disable%20the%20plugin%3F\"><h3>I locked myself out. How do I disable the plugin?<\/h3><\/dt>\n<dd><p>Using FTP, SFTP or your hosting file manager, rename the folder <code>\/wp-content\/plugins\/bypass-guard-for-cloudflare<\/code> to something else, such as <code>bypass-guard-for-cloudflare-disabled<\/code>. WordPress deactivates the plugin automatically, which also switches the filter off. Fix your Cloudflare rule, rename the folder back and reactivate the plugin.<\/p>\n\n<p>With WP-CLI you can simply run <code>wp plugin deactivate bypass-guard-for-cloudflare<\/code>. WP-CLI is never filtered.<\/p><\/dd>\n<dt id=\"why%20does%20the%20settings%20page%20say%20the%20header%20was%20not%20detected%3F\"><h3>Why does the settings page say the header was not detected?<\/h3><\/dt>\n<dd><p>Check that:<\/p>\n\n<ul>\n<li>The Transform Rule is deployed and matches all incoming requests.<\/li>\n<li>The header name is exactly <code>BYPASS-GUARD-TOKEN<\/code> and the value matches the token in the plugin, with no extra spaces.<\/li>\n<li>You are visiting the site through its domain name, not the server's IP address.<\/li>\n<li>The site's DNS records are proxied (orange cloud).<\/li>\n<\/ul>\n\n<p>Some hosts run their own proxy in front of WordPress that strips unfamiliar headers. If the header never arrives even though the Cloudflare rule is correct, ask your host whether custom request headers are passed through.<\/p><\/dd>\n<dt id=\"what%20exactly%20does%20%22detected%22%20mean%3F\"><h3>What exactly does \"Detected\" mean?<\/h3><\/dt>\n<dd><p>It means the plugin has received at least one request with the correct token since the token was generated. It is not a live check: if you later delete or change the Cloudflare rule, the status still shows Detected. Regenerating the token resets it.<\/p><\/dd>\n<dt id=\"how%20do%20i%20change%20the%20token%3F\"><h3>How do I change the token?<\/h3><\/dt>\n<dd><p>Disable the filter, then select <strong>Regenerate Token<\/strong>. The plugin creates a new token and resets the status to Not detected. Update the value in your Cloudflare rule, reload the settings page until the header is detected again, then re-enable the filter.<\/p>\n\n<p>The Regenerate Token button is only shown while the filter is disabled. Changing the token while the filter is on would immediately block every request, including your own, because Cloudflare would still be sending the old value.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20i%20deactivate%20the%20plugin%3F\"><h3>What happens when I deactivate the plugin?<\/h3><\/dt>\n<dd><p>The filter is switched off. Your token, detection status and log are kept. When you activate the plugin again, the filter stays off until you enable it. If you changed your Cloudflare rule in the meantime, regenerate the token so that detection is checked again before you enable the filter.<\/p><\/dd>\n<dt id=\"will%20this%20block%20wp-cron%2C%20site%20health%20or%20other%20loopback%20requests%3F\"><h3>Will this block WP-Cron, Site Health or other loopback requests?<\/h3><\/dt>\n<dd><p>Usually not. When WordPress calls itself through your domain, the request normally goes through Cloudflare and carries the header. On some hosts, however, the server resolves its own domain to a local address and skips Cloudflare. If scheduled tasks or Site Health checks start failing after you enable the filter, this is the likely cause. Switching to a real server cron job that runs WP-Cron without an HTTP request solves it.<\/p><\/dd>\n<dt id=\"will%20external%20services%20that%20connect%20to%20my%20server%20be%20blocked%3F\"><h3>Will external services that connect to my server be blocked?<\/h3><\/dt>\n<dd><p>Only if they connect to your server's IP address directly. Uptime monitors, payment gateway callbacks and webhooks normally use your domain and pass through Cloudflare. Check any integration that is configured with your server's IP address.<\/p><\/dd>\n<dt id=\"does%20the%20log%20store%20personal%20data%3F\"><h3>Does the log store personal data?<\/h3><\/dt>\n<dd><p>Yes. IP addresses and user agents may count as personal data under laws such as the GDPR. The data stays in your own WordPress database and is never sent anywhere. Only the 500 most recent entries are kept and you can clear the log at any time. Depending on your jurisdiction, you may need to mention this in your privacy policy, typically as security logging based on legitimate interest.<\/p><\/dd>\n<dt id=\"how%20secure%20is%20the%20token%3F\"><h3>How secure is the token?<\/h3><\/dt>\n<dd><p>It is 24 hexadecimal characters (96 bits) generated with a cryptographically secure random number generator, and it is compared in constant time to prevent timing attacks. Guessing it is not practical. The realistic risk is leaking it, so treat it like a password, keep SSL\/TLS set to Full (strict) and regenerate it if you think it has been exposed.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>Token generation, header detection and request filtering.<\/li>\n<li>Token regeneration while the filter is disabled.<\/li>\n<li>Built-in setup guide with copy buttons for the header name and token.<\/li>\n<li>Logging of blocked requests, limited to the 500 most recent entries.<\/li>\n<\/ul>","raw_excerpt":"Blocks requests that bypass Cloudflare by requiring a secret token header. For hosts that offer no stronger origin protection.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/380459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=380459"}],"author":[{"embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/gaborangyal"}],"wp:attachment":[{"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=380459"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=380459"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=380459"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=380459"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=380459"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/as.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=380459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}