DISABLE_WP_CRON = true לא חוסם את נקודת הקצה wp-cron.php; הוא רק מונע מ-WordPress להפעיל את בקשת ה-loopback של עצמו. הקובץ נשאר נגיש מהרשת, כך שכל אחד עדיין יכול לגשת אליו ולכפות טעינה מלאה (bootstrap) של WordPress.

נקודת כניסה נסתרת זו עלולה לבזבז CPU, זיכרון ו-PHP workers, במיוחד באתרים עמוסים. אם חשבתם שסגרתם את הדלת, לא עשיתם זאת – עדיין לא.

למה ההגדרה הזו לעיתים קרובות מובנת לא נכון

כאשר WordPress מריץ משימה מתוזמנת, הוא מנסה תחילה לבצע בקשת HTTP מהירה לקובץ wp-cron.php של עצמו. הגדרת DISABLE_WP_CRON ל-true אומרת לליבה (core) לדלג על הבקשה הפנימית הזו. הליבה לא משנה את הגדרות שרת האינטרנט, וגם לא מוסיפה שכבת אימות (authentication) ל-wp-cron.php. הסקריפט נשאר כתובת URL ציבורית שמחזירה סטטוס 200 גם אם תהליך ה-PHP נפסק מוקדם מדי.

תוקף שמגלה את ה-URL יכול לבצע לו ping שוב ושוב, מה שיגרום ל-WordPress לטעון את כל התוספים (plugins), התבניות (themes) ומסד הנתונים בכל פעם מחדש. באחסון משותף או באתר עם PHP workers מוגבלים, נקודת קצה בודדת זו יכולה להפוך לווקטור של מתקפת Denial-of-Service.

מה באמת צריך לעשות

כדי להעביר את העבודה המתוזמנת למתזמן ברמת המערכת (cron, systemd-timer וכו') ולסגור את הדלת הציבורית, בצעו את חמשת השלבים הבאים.

1. השבתת ה-loopback הפנימי

הוסיפו את השורה

define( 'DISABLE_WP_CRON', true );

לקובץ wp-config.php. זה מונע מ-WordPress לנסות לבצע את בקשת ה-HTTP של עצמו, אך זה לא עוצר קריאות חיצוניות.

2. חסימת wp-cron.php בשרת האינטרנט

ב-Nginx, למשל, הכניסו בלוק location שמחזיר 403 Forbidden:

location = /wp-cron.php {
    return 403;
}

השרת כעת דוחה את הבקשה עוד לפני ש-PHP מתחיל, מה שמבטל את עלות ה-bootstrap.

3. הוספת mu-plugin כרשת ביטחון

צרו must-use plugin (שממוקם ב-wp-content/mu-plugins) המתעד (logs) כל בקשה שמגיעה ל-wp-cron.php ויוצא עם קוד 403. זה תופס בקשות שעוקפות בדרך כלשהי את כלל השרת – אולי דרך שם מארח (hostname) שונה או כלל edge של CDN.

4. דיכוי קריאות async של Action Scheduler

תוספים רבים משתמשים בספריית Action Scheduler, שיכולה להפעיל בקשות loopback משלה. השתמשו ב-hook של action_scheduler_queue_runner והחזירו ערך מוקדם (return early) עבור בקשות שאינן CLI, כדי למנוע מהספרייה לנסות לפתוח את הדלתות שלה.

5. ניתוק ה-queue runner מה-hook של WP-Cron

הסירו את ה-Action Scheduler queue runner ברירת המחדל המחובר ל-hook של ה-wp cron. זה מבטיח שהתור ירוץ רק כאשר תפעילו אותו במפורש משורת הפקודה (command line).

הרצת משימות בדרך הנכונה

לאחר שנקודת הקצה הציבורית נחסמה, השתמשו במתזמן המערכת כדי להפעיל את WordPress פעם בדקה (או בכל קצב אחר שתצטרכו) באמצעות WP-CLI:

wp cron event run --due-now

הפקודה הבודדת הזו מעבדת אירועי cron של הליבה וגם את תור ה-Action Scheduler בסביבה מבוקרת, תוך שימוש באותו תהליך PHP שהייתם משתמשים בו לכל משימת CLI אחרת.

יתרונות שניתן למדוד

  • אבטחה – אף משתמש ללא אימות (unauthenticated) לא יכול להתחיל עבודת רקע כבדה.
  • ביצועים – PHP workers נשארים זמינים למבקרים אמיתיים; קפיצות בזיכרון כתוצאה מהרצות cron אקראיות נעלמות.
  • אמינות – התזמון הופך לפרואקטיבי; אתם יודעים בדיוק מתי משימה רצה כי היא מונעת על ידי ה-cron של המערכת, ולא על ידי טעינת דף של מבקר.

מה לעקוב אחרי השינוי

אל תסתמכו על קוד הסטטוס HTTP של wp-cron.php; הוא עדיין עשוי להחזיר 200 גם כאשר הוא נחסם על ידי PHP. במקום זאת:

  • עקבו אחר גודל התור של Action Scheduler. תור שגדל לעיתים קרובות מעיד על הרצות שהוחמצו.
  • בדקו את לוגי השרת (server logs) כדי למצוא רשומות "403" מבלוק ה-location של wp-cron.php.
  • עקבו אחר מספר תהליכי PHP-FPM או FastCGI בזמני עומס כדי לוודא שהעומס ירד.

הערת זהירות

מנהלי מערכת מסוימים משאירים את DISABLE_WP_CRON על false מכיוון שהם מסתמכים על אתרים עם תעבורה נמוכה כדי להפעיל את ה-cron באופן טבעי. הגישה לעיל מסירה את ההסתמכות הזו לחלוטין, אך היא מוסיפה שלב תחזוקה: עליכם לוודא שמתזמן המערכת פועל באופן אמין. אם ה-cron daemon של השרת נכשל, המשימות המתוזמנות ייעצרו. שלבו את ההגדרה עם ניטור של שירות ה-cron של המערכת כדי להימנע ממלכודת זו.

בשורה התחתונה: הגדרת DISABLE_WP_CRON ל-true עוצרת רק את ה-ping של WordPress לעצמו; היא לא סוגרת את נקודת הקצה הציבורית wp-cron.php. חסמו את הקובץ בשרת האינטרנט, הוסיפו mu-plugin כגיבוי, והעבירו את כל העבודה המתוזמנת דרך מתזמן מערכת באמצעות WP-CLI. עשייה זו מאבטחת את האתר, מפחיתה עבודת PHP מיותרת ומעניקה לכם שליטה מדויקת על מועד ביצוע משימות הרקע.