Forum Replies Created

Viewing 7 replies - 1 through 7 (of 7 total)
  • Thread Starter tmaste

    (@tmaste)

    Thread Starter tmaste

    (@tmaste)

    @wfpeter I can reproduce this bug also in WP Engine with a fresh WP installation.

    This is because Wordfence itself always forces the WFWAF_STORAGE_ENGINE=mysqli setting to be used in WP Engine.

    1. Create a new WP Engine site
    2. Convert the site to WP multisite (e.g. sub-directory network)
    3. Create a new subsite, so that you have two blogs: the main blog (e.g. *****.wpenginepowered.com) and the subsite blog (e.g. *****.wpenginepowered.com/subsite)
    4. Install Wordfence to the site
    5. Result: the subsite blog is a lot slower than the main blog

    Testing:

    • When I visit the main site URL *****.wpenginepowered.com/wp-admin/admin-ajax.php, the HTTP response arrives in 0.2 seconds
    • When I visit the subsite URL *****.wpenginepowered.com/subsite/wp-admin/admin-ajax.php, the HTTP response arrives in 1.1 seconds

    I have double-checked that in the subsite on WP Engine, the line $wfWAFStorageEngine->installing = !get_option('wordfenceActivated'); in Wordfence is always true, which is a bug (explained in more detail earlier in this thread).

    Therefore it looks like all subsites in all multisites that use Wordfence in WP Engine (or any environment that uses WFWAF_STORAGE_ENGINE=mysqli) currently have a performance issue caused by this Wordfence bug.

    Thread Starter tmaste

    (@tmaste)

    @wfpeter I have now sent site diagnostics + a debug.log file to the email wftest @ wordfence . com from a fresh WP installation, with only Wordfence installed.

    (I am able to reproduce the problem in that fresh WP installation.)

    Thread Starter tmaste

    (@tmaste)

    Based on the debugging in my previous post, I tried adding the option wordfenceActivated to my non-main blog manually:

    insert into wp_7_options values (NULL, 'wordfenceActivated', 1, 'yes');

    After this, Wordfence doesn’t try to re-run the migrations anymore after every page load of a non-main blog.

    Thread Starter tmaste

    (@tmaste)

    @wfpeter I did some further debugging on this:

    • I deactivated other plugins
    • I removed HyperDB (wp-content/db.php)

    The problem still happens after those changes.

    Could your developers please check if there is a bug in waf/bootstrap.php on line 916 in WP multisite installations?

    That line is trying to determine whether Wordfence has been installed already. Wordfence calls get_option('wordfenceActivated'), but it returns empty for me, since WP is running in the context of a non-main blog, not the main blog, when I visit any non-main blog.

    get_option() returns data from a blog-specific wp_#_options table.

    To me it’s starting to look like the code should instead use get_network_option() and update_network_option(), at least in WP multisite.

    ————————–

    Details:

    After debugging further, my problem seems to be caused by this code in waf/bootstrap.php on line 916:

    if (function_exists('get_option')) {
        // This prints "Blog ID: 7", for example
        error_log('Blog ID: '. get_current_blog_id());
    
        $wfWAFStorageEngine->installing = !get_option('wordfenceActivated');
        $wfWAFStorageEngine->getDb()->installing = $wfWAFStorageEngine->installing;
    }  

    When I visit a non-main blog, the get_option('wordfenceActivated') row tries to find the wordfenceActivated option from the table wp_7_options, for example.

    I only have the wordfenceActivated option in the main blog’s table wp_options, though:

    MySQL [wordpress]> select * from wp_options where option_name = 'wordfenceActivated';
    +-----------+--------------------+--------------+----------+
    | option_id | option_name        | option_value | autoload |
    +-----------+--------------------+--------------+----------+
    |     89243 | wordfenceActivated | 1            | yes      |
    +-----------+--------------------+--------------+----------+

    I don’t have wordfenceActivated it in the non-main blog tables (wp_#_options). For example:

    MySQL [wordpress]> select * from wp_7_options where option_name = 'wordfenceActivated';
    Empty set (0.001 sec)

    Therefore it looks to me like Wordfence only sees itself as installed in the main blog, but doesn’t realize it has been installed in non-main blogs, and therefore Wordfence tries to run its installation/migration logic on every WP page load.

    I have network-activated Wordfence so that it’s active in all blogs.

    I deactivated Wordfence and then network-activated it again, hoping that all WP blogs would receive the wordfenceActivated option. No luck: only the main blog’s wp_options table has the wordfenceActivated option.

    Note: I have not optimized the firewall.

    Thread Starter tmaste

    (@tmaste)

    Hi Peter, thanks for the reply.

    We’ve run some tests on a multisite with MySQLi enabled and we see the correct version being detected in runMigrations() when visiting sub-sites.

    Interesting that you couldn’t reproduce the problem.

    Since I’m not only setting the WFWAF_STORAGE_ENGINE constant, but also setting the following constants, I was wondering if one of those constants is the cause of the problem:

    • WORDFENCE_ALLOW_DIRECT_MYSQLI
    • WFWAF_DB_*
    • WFWAF_TABLE_PREFIX

    But if you tried with those constants defined as well, perhaps the root cause is somewhere else.

    Note that I’m also using HyperDB, i.e. wp-content/db.php, with one read-only DB instance and one read-write DB instance, which is why I set this to false as instructed.

    Are DB_HOSTDB_NAME$table_prefix, or any other database-related values being set differently for the non-main blogs?

    No, those values are the same for all blogs. This is what my wp-config.php basically contains:

    define( 'DB_NAME', [redacted] );
    define( 'DB_USER', [redacted] );
    define( 'DB_PASSWORD', [redacted] );
    define( 'DB_HOST', [redacted] );
    define( 'DB_CHARSET', 'utf8mb4' );
    define( 'DB_COLLATE', 'utf8mb4_swedish_ci' );
    
    $table_prefix = 'wp_';
    
    if ( !defined( 'WFWAF_STORAGE_ENGINE' ) ) {
      define( 'WFWAF_STORAGE_ENGINE', 'mysqli' );
      // For HyperDB
      define( 'WORDFENCE_ALLOW_DIRECT_MYSQLI', false );
      define( 'WFWAF_DB_NAME', DB_NAME );
      define( 'WFWAF_DB_USER', DB_USER );
      define( 'WFWAF_DB_PASSWORD', DB_PASSWORD );
      define( 'WFWAF_DB_HOST', DB_HOST );
      define( 'WFWAF_DB_CHARSET', DB_CHARSET );
      define( 'WFWAF_DB_COLLATE', DB_COLLATE );
      define( 'WFWAF_TABLE_PREFIX', $table_prefix );
    }
    
    if ( !defined('ABSPATH') )
      define('ABSPATH', dirname(__FILE__) . '/');
    
    require_once(ABSPATH . 'wp-settings.php');

    If you could send a diagnostic to wftest @ wordfence . com directly from the link at the top of the Wordfence > Tools > Diagnostics page, that may help. Then click on “Send Report by Email”Please add your forum username where indicated and respond here after you have sent it.

    If the “Send Report by Email” button creates the same diagnostics output as the “Export” button, then unfortunately it sends too much data for my liking (in terms of security). I might sanitize the data by hand first and send it to you manually.

    The debug.log file does not contain any Wordfence-specific errors.

    I’ll get back to this next week.

    • This reply was modified 2 years, 3 months ago by tmaste.
    • This reply was modified 2 years, 3 months ago by tmaste.
    Thread Starter tmaste

    (@tmaste)

    The following is the slowest callstack that is being run in every WP page load (in non-main WP blogs) when using WFWAF_STORAGE_ENGINE mysqli, with the configuration I mentioned earlier:

    wfWAF::run
    -> wfWAF::runMigrations
    -> wfWAFCronFetchRulesEvent::fire
    -> wfWAFHTTP::get
    -> wfWAFHTTP::send
    -> wfWAFHTTPTransportCurl::send
    -> curl_exec

Viewing 7 replies - 1 through 7 (of 7 total)