Free

תן ל-Claude למחוק את ה-IP של שרת המקור מ-DNS ציבורי

ה-IP של שרת המקור שמאחורי Cloudflare דולף דרך תת-הדומיין deploy — שלושה ריפוזיטוריז ב-14 שניות, תוקנו במכה אחת


באותו אחר-צהריים בהיתי בגיטהאב לרגע. שלושה ריפוזיטוריז סגרו PR-ים ב-16:20:31, 16:20:38 וב-16:20:45 — בהפרש של ארבע-עשרה שניות.

  • smarts #38: deploy.smarts.mddeploy.smarts
  • how2claude #13: deploy.how2claude.comdeploy.how2claude
  • pickful #118: deploy.pickful.ai / deploy.pickful.xyzdeploy.pickful / deploy.pickful-alpha

שלושת התיקונים היו מאותה משפחת באגים. במקור פשוט שוחחתי עם Claude על תקלת deploy קטנה לא קשורה ב-how2claude. כבדרך אגב הוא העיף מבט ב-config/deploy.yml ואמר לי שה-IP של שרת המקור של אותה מכונה חשוף לעין כל ב-DNS הציבורי.

אשליה שהוליכה אותי שולל חודשים

כל הפרויקטים שלי יושבים מאחורי Cloudflare. הענן הקטן הכתום בלוח הבקרה של Cloudflare משמעו "רשומה ב-proxy" — בקשות HTTP נוחתות קודם בצומת edge של Cloudflare ומשם לשרת המקור שלי. ה-IP של שרת המקור לא מופיע בתשובות DNS; מה שה-DNS מחזיר הוא IP של anycast של Cloudflare. החלק הזה היה בסדר.

אבל אני עושה deploy עם Kamal. Kamal מבצע SSH לשרת כדי להריץ docker. SSH לא יכול לעבור דרך HTTP proxy, ולכן הייתי צריך hostname שאינו בפרוקסי של Cloudflare כדי לגשת אליו ב-SSH. ההגדרה שלי הייתה:

# config/deploy.yml
servers:
  web:
    - deploy.how2claude.com   # ← רשומת A ישירות ל-IP של שרת המקור, ענן אפור (DNS only)

ב-Cloudflare, how2claude.com ו-www.how2claude.com היו כתומים. deploy.how2claude.com היה אפור. הוא חייב היה להיות אפור, אחרת SSH לא היה מגיע למכונה.

אפור פירושו DNS ציבורי. כל אחד יכול להריץ:

$ dig deploy.how2claude.com +short
<ה-IP של שרת המקור שלי>

ומוסכמת השמות deploy.<domain> היא כשלעצמה רמז ברור — סרוק את תת-הדומיין deploy.* על-פני רשימת דומיינים נפוצים של SaaS, ויש לך קציר של כתובות IP של שרתי מקור שאמורים להסתתר מאחורי Cloudflare.

עוקפים את ה-WAF של Cloudflare, עוקפים rate limiting, עוקפים הגנת DDoS. במרחק dig אחד.

למה Claude שם לב

באותו רגע דיברנו על משהו אחר. ביקשתי ממנו לסקור מסמך deploy שזה עתה כתבתי; הוא פתח את config/deploy.yml להצלבה, הגיע לשורה 7 — - deploy.how2claude.com — עצר לרגע, ואמר משהו בסגנון:

ה-hostname הזה נפתר דרך DNS ציבורי, נכון? כלומר שכל מי שמריץ שאילתת DNS מקבל את ה-IP של שרת המקור, וה-edge proxy של Cloudflare נעקף.

קפאתי לרגע. את זה הייתי צריך לראות מזמן — היה מספיק להעיף עוד מבט באייקון של הענן האפור בזמן ההגדרה של Cloudflare ולשאול את עצמי מה זה אומר — אבל לא עשיתי זאת. התייחסתי ל-hostname הזה כאל משהו "פנימי", אך ורק משום שהקידומת הייתה deploy.. המוח שלי העניק לו בשקט פרטיות שמעולם לא הייתה לו.

ל-Claude אין את ההטיה הזאת. הוא קורא מחרוזת בשדה yaml ושואל את השאלה המכנית: איך המחרוזת הזאת הופכת ל-IP? תשובה: DNS ציבורי. מסקנה: ה-IP של שרת המקור הוא ציבורי.

התיקון: alias ב-/etc/hosts

התיקון הסתבר כפשוט עד מבייש. Kamal מבקש מ-SSH client מקומי לפתור את ה-hostname, כך שה-hostname צריך להיפתר רק על המכונה שלי — לא בכל האינטרנט.

קצרו את ה-hostname ב-yaml:

servers:
  web:
    - deploy.how2claude    # ← לב: בלי .com

ואז תוסיפו שורה ל-/etc/hosts שלי:

198.51.100.42  deploy.how2claude

ל-runners של CI שעושים deploy יש צורך באותה שורה (משתנה סביבה, או echo >> /etc/hosts ישירות ב-workflow).

תוצאה:

  • בשום מקום ב-DNS הציבורי לא קיימת רשומת deploy.how2claude.*
  • תוקפים לא יכולים להוציא את ה-IP דרך DNS — לפחות הצינור הזה נסגר
  • כל פקודות kamal deploy / app exec / app logs ממשיכות לעבוד, כי /etc/hosts נבדק לפני DNS
  • Cloudflare נעשה נקי יותר: אותו תת-דומיין מביך עם ענן אפור פשוט נעלם

האקססורי של מסד הנתונים זקוק לאותו שינוי:

accessories:
  db:
    image: postgres:17
    host: deploy.how2claude   # ← אותו hostname

Claude נשא את זה לכל שלושת הריפוזיטוריז

זה החלק שרציתי להעלות על הכתב.

אחרי שהשטנו את התיקון של how2claude, עמדתי לעבור הקשר. Claude עצר אותי: "אתה משתמש ב-Kamal גם ב-smarts וב-pickful, נכון? תן לי לבדוק גם את אלה."

הוא בדק.

  • smarts: deploy.smarts.md — אותה בעיה, רשומת A ציבורית
  • pickful: deploy.pickful.ai (production), deploy.pickful.xyz (alpha), בנוסף deploy-test1.pickful.ai שמת מזמן ו-deploy.staging.yml שהפנה לדומיין שיצא משימוש, blockgeek.com

pickful היה המסובך מבין השלושה כי היו לו כמה destinations (production / alpha / test2) ומשקעים היסטוריים. תוך כדי, Claude טאטא את destinations המתות staging ו-test1 — ממילא כבר אף אחד לא השתמש בהן, רק רעש.

ה-commits הסופיים:

smarts       6482472   2026-04-27 16:20:31  Use private deploy.smarts alias instead of public deploy.smarts.md (#38)
how2claude   ccc0344   2026-04-27 16:20:38  Use private deploy.how2claude alias instead of public deploy.how2claude.com (#13)
pickful      e6bf9af   2026-04-27 16:20:45  Deploy config hygiene + privatize hostnames (#118)

ארבע-עשרה שניות. כמובן, זה רק GitHub שרוקן את תור ה-merge — העבודה האמיתית התפזרה על שעתיים שלפני. אבל הצורה האפקטיבית הייתה: ממצא אחד, שלושה ריפוזיטוריז מתוקנים.

אם הייתי עובד לבד, הגרסה הריאליסטית היא: לתקן ב-how2claude, לרשום TODO "לעשות גם smarts ו-pickful", ולצפות ב-TODO הזה שוכב ברשימה שלושה חודשים. ראיתי את הרצף הזה בדיוק פעמים רבות.

צ'ק-ליסט שאפשר להעתיק

אם אתה עושה deploy עם Kamal, Capistrano או כל כלי deploy מבוסס SSH:

  1. פתחו את config/deploy*.yml ועשו grep על host: ועל servers:. רשמו כל hostname שמופיע.
  2. הריצו dig +short על כל אחד. כל מה שמחזיר IP של שרת מקור במקום כלום מדליף.
  3. עברו על לוח הבקרה של ה-CDN שלכם (Cloudflare וכו') ושימו לב לתת-דומיינים עם "ענן אפור" — זו קבוצת המועמדים.
  4. שנו את שמם ל-alias בלי TLD (deploy.<project>) ושימו את ה-IP ב-/etc/hosts.
  5. עדכנו גם את ה-deploy job ב-CI. ב-GitHub Actions: echo "$IP deploy.<project>" | sudo tee -a /etc/hosts.
  6. מחקו את רשומת ה-A הציבורית המקורית.

אם הצוות שלכם מנהל כמה פרויקטים שחולקים את אותו תבנית תשתית, כתבו grep בשורה אחת שיסרוק את כל ה-deploy*.yml בכל הריפוזיטוריז — זה אמין יותר מאשר לבדוק אחד-אחד.

הלקח האמיתי

לא Cloudflare כשל ולא Kamal כשל — שני הכלים עשו בדיוק את מה שהיו אמורים לעשות.

הלקח הוא: ערכי ברירת מחדל מטעים אותך בשקט. deploy.<your-domain>.com נשמע כשם פנימי, אבל ל-DNS אין מושג של "פנימי" — רשומת A היא רשומת A, ומרגע שהיא פורסמה היא ציבורית. שם יכול להעניק לך אשליה של פרטיות, ואותו אייקון קטן של ענן אפור בלוח הבקרה של Cloudflare הוא רק הצורה הוויזואלית של אותה אשליה: יושב לו שם בשקט, בלי אזהרות אדומות, אבל במציאות אומר "הרשומה הזאת לא עוברת דרכי".

תנו ל-Claude לקרוא פעם אחת את הקונפיג של ה-deploy שלכם. הוא לא חולק את האשליה.