في هذا الدليل سوف نبني خادم بريد Mail Server كاملاً بأيدينا على Ubuntu 24.04 من الحزم الرسمية Packages للتوزيعة، دون Docker ودون حزمة جاهزة All-in-one كما في دليل تثبيت mailcow، حيث يستقبل Postfix البريد ويرسله، ويخزنه Dovecot ويقدمه للمستخدمين، وتضيف أدوات صغيرة فوقهما فحص SPF وتوقيع DKIM وسياسة DMARC. والسبب أن الحزمة الجاهزة مريحة جداً حتى يحدث أول خطأ، فعندها تكتشف أنك لا تعرف أي مكون Component رفض الرسالة ولماذا، أما هنا فتعرف في النهاية دور كل سطر في الإعداد وأين تبحث عندما تتوقف رسالة.
وهذا الطريق يناسب من يريد أن يفهم البريد الإلكتروني Email من الداخل، ومن يدير نطاقاً واحداً أو بضعة نطاقات بعدد صغير من الصناديق على سيرفر صغير، ولكنه لا يقدم لوحة إدارة ولا بريداً عبر الويب Webmail، فإذا احتاج فريقك إلى ذلك من اليوم الأول فابدأ بـ mailcow. أما قرار استضافة البريد بنفسك أصلاً، والمقارنة بين الخيارات، وخطة نقل المؤسسة، فتجدها في دليل استضافة البريد الإلكتروني للمؤسسات.
في هذا المقال سوف نتناول:
- كيف تمر الرسالة بين السيرفرات، وما دور كل مكون، ولماذا لا يكفي تثبيت Postfix وحده.
- متطلبات السيرفر والمنفذ 25، وسجلات DNS كلها: A وAAAA وMX وPTR وSPF وDKIM وDMARC.
- إعداد Dovecot لصناديق بريد افتراضية Virtual Mailboxes دون حسابات في النظام، وإعداد Postfix للاستقبال على المنفذ 25 والإرسال على المنفذ 587.
- فحص SPF للرسائل الواردة، وتوقيع DKIM والتحقق منه بـ OpenDKIM، وتطبيق سياسة DMARC بـ OpenDMARC.
- الاختبار الكامل: الإرسال والاستقبال والقراءة، ثم محاولة انتحال نطاقك ورؤية الرفض بعينك.
- الحماية من الرسائل المزعجة وتخمين كلمات المرور، والنسخ الاحتياطي، والتحديث، وقراءة سجلات الأخطاء.
كيف تصل الرسالة من سيرفر إلى آخر؟
عندما يرسل شخص من Gmail رسالة إلى [email protected]، يسأل سيرفر Gmail نظام DNS عن سجل MX لنطاقك فيعرف أن بريده يستلمه mail.example.com، ثم يتصل به على المنفذ Port 25 ويسلمه الرسالة عبر بروتوكول SMTP. والبرنامج الذي يستقبل الرسائل وينقلها بين السيرفرات يسمى وكيل نقل البريد Mail Transfer Agent واختصاراً MTA، وهو هنا Postfix. بعد ذلك يسلم Postfix الرسالة إلى Dovecot عبر بروتوكول LMTP فيكتبها في صندوق المستخدم بصيغة Maildir، أي ملف لكل رسالة داخل مجلد، وعندما يفتح المستخدم برنامج البريد Mail Client في هاتفه يتصل بـ Dovecot عبر IMAP على المنفذ 993 ويقرأ الرسالة.
والاتجاه المعاكس يختلف قليلاً، فبرنامج المستخدم لا يرسل على المنفذ 25، وإنما على منفذ الإرسال Submission وهو 587، ويثبت هويته بكلمة المرور، فيسأل Postfix خدمة Dovecot هل كلمة المرور صحيحة (وهذا ما يسمى SASL)، ثم يمرر الرسالة إلى OpenDKIM فيوقعها بمفتاح نطاقك، وبعدها يتصل Postfix بسيرفر المستلم على المنفذ 25 ويسلمها. وفي الطريق يسأل كل طرف نظام DNS عدة أسئلة، والصورة التالية تبين ذلك كله:

في الصورة أعلاه لاحظ التالي:
- Postfix هو الوحيد الذي يتحدث SMTP مع العالم، على المنفذ 25 للسيرفرات الأخرى وعلى المنفذ 587 لمستخدميك، ويقف أمامه postscreen الذي يصد البرامج الآلية Bots قبل أن تكلف Postfix شيئاً.
- Dovecot يقوم بثلاث مهام: يستلم الرسائل من Postfix عبر LMTP ويكتبها على القرص، ويخدم برامج البريد عبر IMAP، ويتحقق من كلمات المرور لصالح Postfix، وبالتالي توجد قائمة المستخدمين في مكان واحد فقط.
- Milter اختصار Mail Filter، وهو برنامج مستقل يمرر له Postfix الرسالة أثناء استقبالها فيعدلها أو يرفضها، وهنا عندنا اثنان: OpenDKIM للتوقيع والتحقق، وOpenDMARC لتطبيق سياسة DMARC.
- فحص SPF يقوم به برنامج صغير ثالث هو policyd-spf، ويعمل بطريقة أخرى تسمى خادم السياسات Policy Server، حيث يسأله Postfix قبل قبول المستلم: هل هذا العنوان مسموح له بالإرسال باسم هذا النطاق؟
لماذا لا يكفي تثبيت Postfix وحده؟
أسهل طريقة يجربها الجميع أن تثبت الحزمة postfix وتختار Internet Site في نافذة الإعداد، فيعمل السيرفر خلال دقائق ويرسل فعلاً، ثم ترسل أول رسالة إلى حسابك في Gmail فتجدها في الرسائل المزعجة Spam، أو يرفضها Gmail برسالة خطأ تذكر عنوان IP الخاص بسيرفرك. والسبب أن السيرفر المستقبل لا يعرف عنك شيئاً، فلا توجد سجلات SPF وDKIM وDMARC تثبت أن سيرفرك يحق له الإرسال باسم نطاقك، وغالباً لا يوجد سجل PTR يعيد اسم سيرفرك عند الاستعلام العكسي، ومنذ فبراير 2024 تشترط Gmail هذه السجلات على من يرسل إليها، وقواعد Yahoo مشابهة.
وقد يتساءل البعض: إذا أضفت سجل SPF فقط، ألا يكفي ذلك؟ والإجابة لا، فالمنتحل يستطيع أن يجتاز SPF لنطاقه هو ويضع From: [email protected] في رسالته، ولذلك نحتاج DKIM وDMARC معه، وقد شرحنا ما يفعله كل واحد من الثلاثة ولماذا لا يكفي أحدها وحده في شرح SPF وDKIM وDMARC للمبتدئين، وفي هذا الدليل سوف نجرب هذا الانتحال على سيرفرنا ونرى من يوقفه.
والمشكلة الثانية في الإعداد البسيط هي الأمان، فإعداد المستخدمين الافتراضي في Postfix وDovecot يعتمد على حسابات النظام System Users، أي أن كل صندوق بريد هو مستخدم Linux يستطيع نظرياً الدخول عبر SSH، ومنفذ الإرسال غير مفعل، وكلمات المرور قد تمر دون تشفير إذا أخطأت في إعداد واحد. لذلك سوف نبني الإعداد الصحيح خطوة خطوة: صناديق افتراضية يملكها مستخدم نظام واحد لا يستطيع الدخول، وكلمات مرور لا تقبل إلا عبر TLS، وإرسال لا يسمح به إلا بعد المصادقة Authentication، وتوقيع وفحص لكل رسالة.
ما تحتاجه قبل أن تبدأ
السيرفر والمنفذ 25
- سيرفر افتراضي VPS بعنوان IPv4 ثابت Static IP: يكفي معالج واحد وذاكرة 1 GB لعدد صغير من الصناديق، ثم احسب مساحة القرص Disk من عدد الصناديق وحجم البريد المتوقع. وابدأ بتأمين السيرفر كما في دليل تأمين خادم VPS من أول دخول قبل أي خطوة هنا.
- المنفذ 25 الصادر مفتوح وسجل PTR قابل للتعديل: كثير من المزودين يحجبون المنفذ 25 افتراضياً، فمثلاً تحجب Hetzner المنفذين 25 و465 على سيرفرات Cloud ولا تفتحهما إلا بطلب بعد شهر من التسجيل ودفع أول فاتورة، وتحجب DigitalOcean منافذ SMTP على Droplets، وتقيد AWS المنفذ 25 على EC2 حتى تطلب رفع القيد. لذلك اسأل المزود قبل الشراء، وراجع دليل اختيار خادم VPS.
- ليس من اتصال المنزل، وبعنوان IP نظيف: عناوين IP المنزلية مدرجة عادة في قوائم الحظر Blocklists كما شرحنا في دليل تشغيل خادمك من إنترنت المنزل، فافحص عنوان سيرفرك في Spamhaus قبل أن تبدأ، وبقية ما تجهزه قبل أي خادم بريد في دليل البريد للمؤسسات.
اسم السيرفر والمنافذ
هنا اسمان يخلط بينهما كثيرون: اسم السيرفر مثل mail.example.com، وبه يعرف السيرفر نفسه في التحية HELO وله تصدر الشهادة Certificate وإليه يشير سجل PTR، ونطاق البريد مثل example.com وهو ما يظهر بعد @ في العناوين. ابدأ بضبط اسم السيرفر:
sudo hostnamectl set-hostname mail.example.com
hostname -fثم افتح المنافذ التي سوف نستخدمها في جدار الحماية Firewall:
| المنفذ | الخدمة | الاستخدام |
|---|---|---|
| 25/tcp | SMTP | استقبال البريد من السيرفرات الأخرى (وخروجه إليها) |
| 587/tcp | Submission | إرسال البريد من برامج المستخدمين بعد STARTTLS وكلمة المرور |
| 993/tcp | IMAPS | قراءة البريد عبر TLS |
| 80/tcp | HTTP | إصدار شهادة Let's Encrypt وتجديدها عبر التحقق من ملكية النطاق عبر HTTP (HTTP Challenge) |
sudo ufw allow 25,587,993,80/tcp
sudo ufw statusولاحظ أننا لا نفتح المنفذ 143 (IMAP دون تشفير) ولا المنفذين 110 و995 (POP3)، والسبب أن كل خدمة لا تحتاجها هي باب إضافي يطرقه المخترقون. وكذلك يوصي RFC 8314 بالمنفذ 465 مع TLS مباشر Implicit TLS للإرسال، ونكتفي هنا بالمنفذ 587 لأن كل برامج البريد تدعمه، وتستطيع إضافة 465 لاحقاً بخدمة submissions في master.cf.
سجلات DNS
سجلات DNS هي هوية سيرفرك أمام السيرفرات الأخرى، وقد شرحنا أنواعها بالتفصيل في شرح DNS وسجلاته للمبتدئين، وعرفناها باختصار في دليل مصطلحات الاستضافة الذاتية. أضف السجلات التالية في لوحة DNS الخاصة بنطاقك، وضع عنوان سيرفرك مكان 203.0.113.10 و2001:db8::10، أما سجل DKIM فسوف نضيفه بعد إنشاء المفتاح:
| الاسم | النوع | القيمة | الغرض |
|---|---|---|---|
mail.example.com | A | 203.0.113.10 | عنوان السيرفر |
mail.example.com | AAAA | 2001:db8::10 | فقط إذا كان IPv6 مفعلاً لديك، ومعه PTR خاص به |
example.com | MX | 10 mail.example.com | أين تسلم السيرفرات الأخرى بريد النطاق، والقيمة اسم وليست عنوان IP |
example.com | TXT | v=spf1 mx -all | SPF: السيرفرات المذكورة في MX وحدها ترسل باسم النطاق |
mail.example.com | TXT | v=spf1 a -all | SPF لاسم السيرفر نفسه الذي يظهر في HELO |
_dmarc.example.com | TXT | v=DMARC1; p=none; rua=mailto:[email protected] | سياسة DMARC وعنوان التقارير |
203.0.113.10 | PTR | mail.example.com | الاستعلام العكسي، ويضبط من لوحة مزود السيرفر وليس من لوحة DNS |
في الجدول أعلاه لاحظ التالي:
- PTR أو rDNS: تجده في لوحة مزود ال VPS باسم Reverse DNS، ويجب أن يعيد الاسم
mail.example.comنفسه الذي يشير سجله A إلى العنوان نفسه، وهذا ما تسميه Gmail سجلات DNS في الاتجاهين Forward-confirmed reverse DNS، وبدونه ترفض كثير من السيرفرات الاتصال أصلاً. - SPF: سجل واحد فقط لكل نطاق كما يشترط RFC 7208، فإذا كنت ترسل أيضاً عبر خدمة أخرى مثل نشرة بريدية أو نظام تذاكر فأضفها إلى السجل نفسه، والسبب أن وجود سجلين يجعل النتيجة PermError فيفشل الفحص، ومعنى كل جزء في السجل مثل
-allو~allتجده في شرح SPF وDKIM وDMARC. - SPF لاسم السيرفر: بعض السيرفرات تفحص الاسم الذي يقدمه سيرفرك في HELO، وخصوصاً في رسائل الارتداد Bounces التي يكون عنوان مغلفها فارغاً، لذلك أضف له سجلاً خاصاً كما يوصي RFC 7208.
- DMARC: ابدأ بالقيمة
p=noneواقرأ التقارير التي تصل إلى[email protected]، ثم انتقل إلىp=quarantineثمp=rejectعلى مراحل، ولا تضع الوسمpctفي السجلات الجديدة، فقد حذفه المعيار الحالي RFC 9989.
بعد نشر السجلات تحقق منها من أي جهاز:
dig +short A mail.example.com
dig +short MX example.com
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short -x 203.0.113.10تثبيت الحزم
كل ما نحتاجه موجود في مستودعات Ubuntu 24.04 الرسمية Repositories. وعند تثبيت postfix سوف تظهر نافذة تسأل عن نوع الإعداد، فنجيب عنها مسبقاً بالأمر debconf-set-selections حتى لا تتوقف عندها، والسبب أننا سوف نستبدل ملف الإعداد كاملاً بعد قليل:
echo "postfix postfix/main_mailer_type select Internet Site" | sudo debconf-set-selections
echo "postfix postfix/mailname string mail.example.com" | sudo debconf-set-selections
sudo apt update
sudo apt install postfix dovecot-imapd dovecot-lmtpd opendkim opendkim-tools \
postfix-policyd-spf-python opendmarc fail2ban certbot swaksوالإصدارات التي تثبتها هذه الأوامر وقت كتابة الدليل هي Postfix 3.8.6 وDovecot 2.3.21 وOpenDKIM 2.11.0~beta2 وOpenDMARC 1.4.2 وpolicyd-spf 3.0.4، ولاحظ أن الحزم postfix وdovecot-* في المستودع main فتصلها التحديثات الأمنية من Ubuntu خمس سنوات، أما opendkim وopendmarc وpostfix-policyd-spf-python وfail2ban ففي المستودع universe الذي يصونه المجتمع، وتغطيه التحديثات الأمنية الموسعة ESM عبر Ubuntu Pro المجاني للاستخدام الشخصي حتى خمسة أجهزة.
شهادة TLS من Let's Encrypt
يحتاج Postfix وDovecot إلى شهادة صالحة للاسم mail.example.com، وأبسط طريقة على سيرفر لا يوجد فيه خادم ويب Web Server هي أن يشغل certbot خادم ويب مؤقتاً على المنفذ 80 للتحقق ثم يغلقه:
sudo certbot certonly --standalone -d mail.example.com \
--agree-tos -m [email protected] --no-eff-email \
--deploy-hook "systemctl reload postfix dovecot"تحفظ الشهادة في /etc/letsencrypt/live/mail.example.com/: الملف fullchain.pem وفيه الشهادة مع السلسلة Chain، والملف privkey.pem وفيه المفتاح الخاص Private Key. والخيار --deploy-hook يحفظه certbot مع إعداد الشهادة، فبعد كل تجديد تلقائي يعيد تحميل Postfix وDovecot حتى يقرآ الشهادة الجديدة، والسبب أن الخدمتين تقرآن الملف عند التشغيل فقط، وبدون هذا الخيار سوف تستمران في تقديم الشهادة القديمة حتى تنتهي صلاحيتها. وتستطيع تجربة التجديد دون إصدار حقيقي:
sudo certbot renew --dry-run--webroot بدلاً من --standalone، أو أصدر الشهادة عبر التحقق من ملكية النطاق عبر ال DNS (DNS Challenge) بإضافة certbot الخاصة بمزود DNS لديك.صناديق بريد دون حسابات في النظام
الإعداد الافتراضي يجعل كل صندوق بريد مستخدماً في Linux، وهذا غير مناسب إطلاقاً لخادم بريد، فكل مستخدم بريد يصبح حساباً في النظام له كلمة مرور قد تفتح SSH، وإضافة صندوق تحتاج إلى صلاحيات root. والحل الأنسب هو الصناديق الافتراضية Virtual Mailboxes: مستخدم نظام واحد اسمه vmail لا يستطيع الدخول ويملك كل الرسائل على القرص، وقائمة المستخدمين وكلمات مرورهم في ملف نصي يقرأه Dovecot وحده. الآن سوف ننشئ هذا المستخدم برقم ثابت 5000 حتى يبقى الرقم نفسه إذا نقلت البريد إلى سيرفر آخر:
sudo groupadd -g 5000 vmail
sudo useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /var/vmail -M vmail
sudo install -d -o vmail -g vmail -m 750 /var/vmailثم نولد الهاش Hash لكلمة مرور أول صندوق بخوارزمية ARGON2ID، وهي دالة اشتقاق مفاتيح Key Derivation Function بطيئة عمداً وتحتاج إلى ذاكرة كبيرة في كل محاولة، والسبب أن من يسرق ملف المستخدمين سوف يحتاج إلى وقت طويل جداً لتجربة كل كلمة مرور. ونفذ الأمر دون أن تكتب كلمة المرور فيه حتى لا تبقى في سجل الأوامر History، فسوف يطلبها منك مرتين:
sudo doveadm pw -s ARGON2IDوالمخرج سوف يكون سطراً مثل التالي:
{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$6pGgoXZvZ5ZQAZ56OSkoBA$OtCqVjFchJ2sQtyJkgjv1/l1c6we1Zei8iyVlJYlu/Qانسخ السطر كاملاً وأنشئ ملف المستخدمين /etc/dovecot/users، حيث يحمل كل سطر العنوان الكامل ثم نقطتين ثم الهاش:
sudo nano /etc/dovecot/users[email protected]:{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$6pGgoXZvZ5ZQAZ56OSkoBA$OtCqVjFchJ2sQtyJkgjv1/l1c6we1Zei8iyVlJYlu/Qsudo chown root:dovecot /etc/dovecot/users
sudo chmod 640 /etc/dovecot/usersوبهذا الشكل يقرأ الملف root ومجموعة dovecot فقط، ولا يستطيع أي مستخدم آخر على السيرفر أن يرى حتى الهاشات.
إعداد Dovecot
يأتي Dovecot في Ubuntu بملف رئيسي /etc/dovecot/dovecot.conf يضم أكثر من عشرين ملفاً في conf.d، وتعديل الإعداد موزعاً عليها يجعل من الصعب أن تعرف ما المفعل فعلاً. لذلك سوف نكتب الإعداد كله في ملف واحد بدلاً من الملف الرئيسي، فيصبح كل ما يفعله Dovecot أمامك في صفحة واحدة. احتفظ بنسخة من الملف الأصلي ثم اكتب الملف الجديد:
sudo cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
sudo nano /etc/dovecot/dovecot.conf# /etc/dovecot/dovecot.conf: the whole configuration in one file
protocols = imap lmtp
listen = *, ::
# Virtual users: one system user (vmail) owns every mailbox
mail_location = maildir:/var/vmail/%d/%n/Maildir
mail_uid = vmail
mail_gid = vmail
first_valid_uid = 5000
last_valid_uid = 5000
mail_privileged_group = vmail
namespace inbox {
inbox = yes
separator = /
mailbox Drafts {
special_use = \Drafts
auto = subscribe
}
mailbox Junk {
special_use = \Junk
auto = subscribe
}
mailbox Sent {
special_use = \Sent
auto = subscribe
}
mailbox Trash {
special_use = \Trash
auto = subscribe
}
}
# TLS
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_min_protocol = TLSv1.2
# Authentication: passwd-file, no system accounts
auth_mechanisms = plain login
auth_username_format = %Lu
disable_plaintext_auth = yes
passdb {
driver = passwd-file
args = scheme=ARGON2ID /etc/dovecot/users
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}
service imap-login {
inet_listener imap {
port = 0
}
inet_listener imaps {
port = 993
ssl = yes
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
protocol lmtp {
postmaster_address = [email protected]
}في الإعداد أعلاه لاحظ التالي:
mail_locationيضع بريد[email protected]في/var/vmail/example.com/info/Maildir، حيث%dهو النطاق و%nهو الجزء قبل @، وصيغة Maildir تحفظ كل رسالة في ملف مستقل، فلا يفسد صندوق كامل إذا انقطع التيار أثناء الكتابة، ويسهل نسخه احتياطياً.first_valid_uidوlast_valid_uidيمنعان Dovecot من الكتابة بأي هوية غيرvmail، فحتى لو أخطأت في إعداد مستخدم لن يكتب Dovecot بصلاحيات root.- الكتلة
namespace inboxتنشئ المجلدات الأساسية تلقائياً وتعلن نوع كل مجلد Special Use، فيعرف Thunderbird والهاتف أين يحفظان الرسائل المرسلة والمحذوفة دون إعداد يدوي. ssl = requiredمعdisable_plaintext_auth = yesيعنيان أن كلمة المرور لا تقبل أبداً على اتصال غير مشفر، والعلامة<قبل المسار تعني اقرأ محتوى الملف وليس النص نفسه.passwd-fileيقرأ كلمات المرور من الملف الذي أنشأناه، وuserdb staticيعطي كل المستخدمين الهوية نفسهاvmail، فلا نحتاج إلى أن نكتب لكل مستخدم رقماً ومجلداً.port = 0يغلق IMAP غير المشفر على المنفذ 143، ويبقى المنفذ 993 وحده.- المقبسان Sockets في
/var/spool/postfix/private/هما نقطة الالتقاء مع Postfix: الأول لتسليم الرسائل عبر LMTP، والثاني ليسأل Postfix عن كلمات المرور كما في دليل Dovecot الرسمي لربط SASL. ووضعناهما داخل مجلد Postfix لأن خدمات Postfix تعمل في بيئة معزولة Chroot داخل/var/spool/postfixولا ترى ملفات خارجه.
أعد تشغيل Dovecot ثم اختبر كلمة المرور ومعلومات المستخدم:
sudo systemctl restart dovecot
sudo doveadm auth test [email protected]
sudo doveadm user [email protected]والمخرج سوف يكون كما يلي:
passdb: [email protected] auth succeeded
extra fields:
[email protected]
field value
uid 5000
gid 5000
home /var/vmail/example.com/info
mail maildir:/var/vmail/example.com/info/Maildirإعداد Postfix
إعداد Postfix في ملفين: main.cf للإعدادات العامة، وmaster.cf للخدمات التي تعمل وعلى أي منافذ. وكما فعلنا مع Dovecot سوف نكتب main.cf كاملاً بدلاً من تعديل الملف الذي ولده المثبت، والسبب أن إضافة الإعدادات في آخر الملف تترك قيماً مكررة يحذرك منها Postfix في كل أمر، ولا تعرف أي القيمتين هي المستخدمة.
الملف main.cf
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
sudo nano /etc/postfix/main.cf# /etc/postfix/main.cf
compatibility_level = 3.6
smtpd_banner = $myhostname ESMTP
biff = no
append_dot_mydomain = no
readme_directory = no
# Server identity
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
mydestination = localhost
mynetworks = 127.0.0.0/8 [::1]/128
inet_interfaces = all
inet_protocols = all
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
recipient_delimiter = +
message_size_limit = 52428800
mailbox_size_limit = 0
# Virtual domains and mailboxes, delivered to Dovecot over LMTP
virtual_mailbox_domains = example.com
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_alias_maps = hash:/etc/postfix/virtual
virtual_transport = lmtp:unix:private/dovecot-lmtp
# TLS for incoming connections (port 25 and 587)
smtpd_tls_chain_files = /etc/letsencrypt/live/mail.example.com/privkey.pem, /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_security_level = may
smtpd_tls_protocols = >=TLSv1.2
smtpd_tls_mandatory_protocols = >=TLSv1.2
smtpd_tls_loglevel = 1
# TLS for outgoing connections to other servers
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# SASL: Postfix asks Dovecot to check passwords (enabled on 587 only)
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = no
# Who may relay, and the SPF check for incoming mail
smtpd_helo_required = yes
disable_vrfy_command = yes
smtpd_forbid_bare_newline = normalize
smtpd_forbid_bare_newline_exclusions = $mynetworks
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/policyd-spf
policyd-spf_time_limit = 3600
# Milters: OpenDKIM (sign and verify) then OpenDMARC
milter_default_action = accept
smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:8893
non_smtpd_milters = inet:127.0.0.1:8891
# postscreen in front of port 25
postscreen_access_list = permit_mynetworks
postscreen_blacklist_action = drop
postscreen_greet_action = enforce
postscreen_dnsbl_sites = zen.spamhaus.org=127.0.0.[2..11]*3, bl.spamcop.net=127.0.0.2*2
postscreen_dnsbl_threshold = 3
postscreen_dnsbl_action = enforce
# Limits per client IP
smtpd_client_connection_rate_limit = 30
smtpd_client_message_rate_limit = 60
smtpd_client_recipient_rate_limit = 200
smtpd_soft_error_limit = 10
smtpd_hard_error_limit = 20في الإعداد أعلاه لاحظ التالي:
mydestination = localhostمعvirtual_mailbox_domains = example.com: النطاقexample.comلا يسلم لحسابات النظام، وإنما يعامل نطاقاً افتراضياً يسلم بريده إلى Dovecot عبرvirtual_transport، ولا تضع النطاق نفسه في الإعدادين معاً أبداً كما ينبه دليل النطاقات الافتراضية.virtual_mailbox_mapsقائمة العناوين الموجودة فعلاً، وبها يرفض Postfix الرسالة إلى عنوان غير موجود أثناء الاتصال برمز 550، بدلاً من أن يقبلها ثم يرسل رسالة ارتداد إلى عنوان قد يكون مزيفاً، وهذا ما يسمى Backscatter ويضع سيرفرك في قوائم الحظر.smtpd_tls_chain_filesهي الطريقة الحديثة لتحديد المفتاح ثم الشهادة في سطر واحد، وsmtpd_tls_security_level = mayعلى المنفذ 25 تعني أن TLS متاح ولكنه ليس إجبارياً، والسبب أن بعض السيرفرات القديمة لا تدعمه، وRFC 3207 يمنع إجبار TLS على سيرفر MX عام. أما على المنفذ 587 فسوف نجعله إجبارياً فيmaster.cf.smtpd_sasl_auth_enable = noهنا، ثم نفعله على المنفذ 587 فقط، فلا يقبل المنفذ 25 كلمات مرور إطلاقاً، وبالتالي لا يستطيع المخترق تخمين كلمات المرور عليه.smtpd_relay_restrictionsأهم سطر في الملف: لا يمرر Postfix رسالة إلى نطاق خارجي إلا إذا جاءت من السيرفر نفسه أو من مستخدم سجل دخوله، وبدونه يصبح سيرفرك مرحلاً مفتوحاً Open Relay يرسل من خلاله أي شخص في العالم، وتجده في قوائم الحظر خلال ساعات.smtpd_forbid_bare_newline = normalizeيغلق هجوم تهريب SMTP (SMTP Smuggling) كما سيأتي في قسم الحماية، وقيمته الافتراضية في Postfix 3.8 هيno، لذلك نكتبها صراحة.milter_default_action = acceptيعني أنه إذا توقف OpenDKIM أو OpenDMARC يستمر Postfix في قبول البريد دون فحص بدلاً من أن يرفض كل شيء، وهذا اختيار للتوافرية Availability على حساب الفحص، ويمكنك أن تجعلهاtempfailإذا كنت تفضل أن تتأخر الرسائل على أن تمر دون توقيع.- OpenDKIM وOpenDMARC يستمعان على
127.0.0.1عبر TCP بدلاً من المقبس الافتراضي في/run، والسبب نفسه: خدمةsmtpdتعمل في Chroot ولا ترى/run.
قوائم العناوين
الآن سوف ننشئ ثلاث قوائم صغيرة: العناوين الموجودة، والأسماء المستعارة Aliases، وأي عنوان يحق لكل مستخدم أن يرسل باسمه. ولاحظ أن القيمة في vmailbox لا يستخدمها Postfix عند التسليم عبر LMTP، فيكفي أي نص مثل OK، والمهم وجود العنوان في القائمة:
sudo tee /etc/postfix/vmailbox >/dev/null <<'EOF'
[email protected] OK
EOF
sudo tee /etc/postfix/virtual >/dev/null <<'EOF'
[email protected] [email protected]
[email protected] [email protected]
[email protected] [email protected]
[email protected] [email protected]
EOF
sudo tee /etc/postfix/sender_login >/dev/null <<'EOF'
[email protected] [email protected]
EOF
sudo postmap /etc/postfix/vmailbox /etc/postfix/virtual /etc/postfix/sender_login
sudo newaliasesالعنوان postmaster يجب أن يستقبل البريد في كل نطاق كما يشترط RFC 5321، وabuse يوصي به RFC 2142، وإليهما تصل الشكاوى وتقارير المشكلات، وdmarc لتقارير DMARC، وroot حتى تصلك رسائل النظام مثل أخطاء cron. وكل مرة تعدل فيها ملفاً من هذه الملفات نفذ postmap عليه، والسبب أن Postfix يقرأ النسخة المفهرسة .db وليس الملف النصي.
/etc/dovecot/users لكلمات المرور و/etc/postfix/vmailbox للعناوين. عند إضافة صندوق جديد أضفه في الملفين ثم نفذ postmap، وعند حذف صندوق احذفه من الملفين، وإلا قبل Postfix رسائل لصندوق لا يعرفه Dovecot فترتد بعد قبولها.الملف master.cf: المنفذ 587 وpostscreen
افتح /etc/postfix/master.cf، وفي أوله ستجد خدمة smtp مفعلة وتحتها أربعة أسطر معطلة لـ postscreen. عطل السطر الأول وفعل الأربعة حتى تصبح بداية الملف كما يلي:
sudo nano /etc/postfix/master.cf#smtp inet n - y - - smtpd
smtp inet n - y - 1 postscreen
smtpd pass - - y - - smtpd
dnsblog unix - - y - 0 dnsblog
tlsproxy unix - - y - 0 tlsproxyثم أضف في آخر الملف خدمة الإرسال submission وخدمة فحص SPF:
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_sender_login_maps=hash:/etc/postfix/sender_login
-o smtpd_sender_restrictions=reject_sender_login_mismatch
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=
-o milter_macro_daemon_name=ORIGINATING
policyd-spf unix - n n - 0 spawn
user=policyd-spf argv=/usr/bin/policyd-spfفي الإعداد أعلاه لاحظ التالي:
- الآن يستقبل postscreen كل اتصال على المنفذ 25، ولا يمرره إلى
smtpdإلا بعد أن يجتاز فحوصه، كما سيأتي في قسم الحماية. - على المنفذ 587
smtpd_tls_security_level=encryptيجعل TLS إجبارياً، وsmtpd_tls_auth_only=yesيخفي أمر AUTH حتى يبدأ التشفير، فلا يرسل أي برنامج كلمة المرور نصاً واضحاً ولو أخطأ المستخدم في إعداده. smtpd_sender_login_mapsمعreject_sender_login_mismatchيمنعان المستخدم الذي سجل دخوله بحسابinfoمن أن يرسل باسم[email protected]، والسبب أن الحساب المسروق يجب ألا يستطيع انتحال زملائه.smtpd_recipient_restrictions=فارغة على 587 لأن رسائل المستخدمين لا تحتاج إلى فحص SPF، فهي من سيرفرنا نفسه.- خدمة
policyd-spfيشغلها Postfix عند الطلب بمستخدمpolicyd-spfالذي أنشأته الحزمة، كما في دليل خوادم السياسات.
فحص SPF للرسائل الواردة
سجل SPF الذي أضفناه يحمي نطاقك عند الآخرين، أما فحص الرسائل التي تصلك فيقوم به policyd-spf. وملف إعداده /etc/postfix-policyd-spf-python/policyd-spf.conf يأتي بقيم مناسبة، ونضيف إليه سطرين حتى يكتب النتيجة بصيغة Authentication-Results التي يقرأها OpenDMARC:
sudo nano /etc/postfix-policyd-spf-python/policyd-spf.confdebugLevel = 1
TestOnly = 1
HELO_reject = Fail
Mail_From_reject = Fail
PermError_reject = False
TempError_Defer = False
skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1
Header_Type = AR
Authserv_Id = mail.example.comفي الإعداد أعلاه لاحظ التالي:
TestOnly = 1اسم مضلل، فالقيمة1هي التي تفعل الرفض الحقيقي، والقيمة0هي وضع الاختبار الذي يضيف الترويسة Header فقط، فلا تغيرها ظناً أنك تلغي وضع الاختبار.Mail_From_reject = Failيرفض الرسالة عندما تكون نتيجة SPF هيfailفقط، أي عندما يقول صاحب النطاق صراحة-all، أماsoftfailفتمر مع ترويسة تسجل النتيجة.Header_Type = ARمعAuthserv_Idتجعل النتيجة ترويسةAuthentication-Resultsباسم سيرفرك، فيثق بها OpenDMARC لاحقاً.
توقيع DKIM: الختم الذي لا يمكن تزويره
في هذا القسم سوف يوقع OpenDKIM كل رسالة تخرج من سيرفرك بالمفتاح الخاص Private Key الذي لا يغادره، ويضع التوقيع في ترويسة DKIM-Signature كما في RFC 6376، وننشر المفتاح العام Public Key في سجل TXT ليتحقق منه السيرفر المستقبل. وقد شرحنا فكرة التوقيع الرقمي وما يثبته DKIM وما لا يثبته في شرح SPF وDKIM وDMARC للمبتدئين.
لماذا OpenDKIM وليس Rspamd؟
هناك أداتان شائعتان للتوقيع مع Postfix. الأولى Rspamd، وهو نظام كامل لمكافحة الرسائل المزعجة يوقع DKIM ويفحص SPF وDMARC ويتعلم من الرسائل، وهو الذي يستخدمه mailcow، ولكنه أثقل بكثير ويحتاج إلى Redis، ويوصي مطوروه بحزمهم الرسمية بدلاً من حزمة التوزيعة، والسبب واضح عند المقارنة: Ubuntu 24.04 يقدم الإصدار 3.8.1 بينما الإصدار الحالي 4.2.1. والثانية OpenDKIM، وهو برنامج صغير بلغة C يفعل شيئاً واحداً هو التوقيع والتحقق، ويأتي في مستودعات Ubuntu جاهزاً.
واخترنا OpenDKIM في هذا الدليل لأن هدفه أن ترى كل مكون منفصلاً وتفهم دوره، ولأنه الأخف على سيرفر صغير، ولكن عليك أن تعرف حالته بصراحة: آخر إصدار منشور منه هو 2.11.0 Beta2 في نوفمبر 2018، والحزمة في Ubuntu مبنية عليه، بينما يستمر الفرع develop في GitHub في تلقي إصلاحات حتى 2026 دون إصدار جديد. وهذا مقبول لأداة صغيرة ناضجة يصونها Debian وUbuntu، فإذا أردت لاحقاً فلتراً حقيقياً للرسائل المزعجة فالانتقال إلى Rspamd هو الخطوة الطبيعية، وهو يحل محل OpenDKIM وOpenDMARC وpolicyd-spf معاً.
إنشاء المفتاح ونشره
نولد زوج المفاتيح بطول 2048 بت، والمحدد Selector هو اسم المفتاح داخل النطاق، وهنا mail، وبه تستطيع لاحقاً تدوير المفاتيح Key Rotation بنشر مفتاح جديد بمحدد آخر دون أن تتعطل الرسائل القديمة:
sudo mkdir -p /etc/opendkim/keys/example.com
sudo opendkim-genkey -b 2048 -d example.com -s mail -D /etc/opendkim/keys/example.com
sudo chown -R opendkim:opendkim /etc/opendkim
sudo chmod 700 /etc/opendkim/keys/example.com
sudo cat /etc/opendkim/keys/example.com/mail.txtوالمخرج سوف يكون كما يلي:
mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkU7h3AxshIPmmJFDUZf/PIzAteClMy1JsdmU4Fz/7vdrncSPPx8tPN9l42tNeOcMiT5/+xoaxdceSfX3OjPNvJKGQoVu2M+AjZ7pbF1+FORYuxqcsjTIGoItLzr3sfxRA0anXbcFT+p08/FigxM2GV9wUlyDM9QBkf3fWJ+CkL6Yq0BBXUtMddTR9zFYdL9brtVYXLQ+XTLk6s"
"ArEdnZ+v3alTC6icstA/qNcNyhiqg0T438o609WySHCr41eIWobYdl7rd8X797utnOgcV5tge3AaEg4Mc+MKCqDjdjKJCODoMS2gMHIv/QzqZFJVLBziSNhY5IpfUhnxfZRQqNPwIDAQAB" ) ; ----- DKIM key mail for example.comأضف سجل TXT باسم mail._domainkey.example.com، وقيمته النصوص التي بين علامات التنصيص متتالية دون فواصل، أي تبدأ بـ v=DKIM1; h=sha256; k=rsa; p=MIIB… وتنتهي بـ …IDAQAB. ولاحظ أن النص طويل، وسجل TXT لا يقبل أكثر من 255 حرفاً في السلسلة الواحدة، لذلك قسمه opendkim-genkey إلى سلسلتين، وبعض لوحات DNS تقسمه بنفسها إذا لصقته كاملاً، ولا مشكلة في ذلك. أما الملف mail.private فهو المفتاح الخاص، وإذا تسرب يستطيع حامله أن يوقع رسائل باسم نطاقك، لذلك صلاحياته للمستخدم opendkim وحده.
إعداد OpenDKIM
sudo cp /etc/opendkim.conf /etc/opendkim.conf.orig
sudo nano /etc/opendkim.conf# /etc/opendkim.conf
Syslog yes
SyslogSuccess yes
LogWhy yes
UserID opendkim
UMask 007
PidFile /run/opendkim/opendkim.pid
Socket inet:[email protected]
# sign mail from our domain, verify everything else
Mode sv
Domain example.com
Selector mail
KeyFile /etc/opendkim/keys/example.com/mail.private
InternalHosts 127.0.0.1, ::1
Canonicalization relaxed/simple
OversignHeaders From
AuthservID mail.example.com
TrustAnchorFile /usr/share/dns/root.keyفي الإعداد أعلاه لاحظ التالي:
Mode svيعني التوقيع Sign والتحقق Verify معاً، فيوقع OpenDKIM الرسائل التي من نطاقك إذا جاءت منInternalHostsأو من مستخدم سجل دخوله على المنفذ 587، ويتحقق من توقيع كل رسالة واردة.DomainوSelectorوKeyFileتكفي لنطاق واحد، وإذا أضفت نطاقات أخرى فاستخدم الخيارينKeyTableوSigningTableالموضحين في توثيق opendkim.conf.Canonicalization relaxed/simpleيتسامح مع تغيير المسافات وحالة الأحرف في الترويسات، والسبب أن بعض السيرفرات في الطريق تعيد ترتيب المسافات فيفشل التوقيع دون أن يغير أحد المعنى.OversignHeaders Fromيمنع أي طرف في الطريق من إضافة ترويسة From ثانية إلى رسالة موقعة.TrustAnchorFileيجعل OpenDKIM يتحقق من توقيع DNSSEC للمفتاح إذا كان نطاق المرسل يدعمه، ولذلك سوف ترى كلمةunprotectedأوnot secureفي النتائج عندما لا يكون النطاق موقعاً بـ DNSSEC، وهي معلومة وليست خطأ.
أعد تشغيل OpenDKIM ثم اختبر أن المفتاح المنشور في DNS يطابق المفتاح الخاص، وانتظر قبل ذلك حتى ينتشر السجل:
sudo systemctl restart opendkim
sudo opendkim-testkey -d example.com -s mail -vvvوالمخرج سوف يكون كما يلي:
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/opendkim/keys/example.com/mail.private
opendkim-testkey: checking key 'mail._domainkey.example.com'
opendkim-testkey: key not secure
opendkim-testkey: key OKالسطر key OK هو المهم، وkey not secure معناه أن نطاقك غير موقع بـ DNSSEC فقط.
DMARC: ماذا يفعل المستقبل عند الفشل؟
بعد SPF وDKIM يبقى سؤال: ماذا يفعل السيرفر المستقبل إذا فشلا؟ وهنا يأتي DMARC بسياستك Policy (none أو quarantine أو reject) وشرط التطابق Alignment بين النطاق الظاهر في From والنطاق الذي اجتاز SPF أو وقع بـ DKIM، وهذا الشرط هو الذي سوف يوقف رسالة المنتحل في قسم الاختبار، وتفاصيله في شرح SPF وDKIM وDMARC.
وسجلك أضفناه في قسم DNS، أما تطبيق DMARC على الرسائل التي تصلك أنت فاختياري ويقوم به OpenDMARC، وآخر إصدار منه 1.4.2 في ديسمبر 2021، ويقرأ نتائج SPF وDKIM التي كتبها policyd-spf وOpenDKIM ثم يطبق سياسة نطاق المرسل:
sudo cp /etc/opendmarc.conf /etc/opendmarc.conf.orig
sudo nano /etc/opendmarc.conf# /etc/opendmarc.conf
Syslog true
UserID opendmarc
UMask 0002
PidFile /run/opendmarc/opendmarc.pid
Socket inet:[email protected]
AuthservID mail.example.com
TrustedAuthservIDs mail.example.com
PublicSuffixList /usr/share/publicsuffix/public_suffix_list.dat
IgnoreAuthenticatedClients true
RejectFailures true
RequiredHeaders trueفي الإعداد أعلاه لاحظ التالي:
TrustedAuthservIDsيجعل OpenDMARC يثق بترويسات Authentication-Results التي كتبها سيرفرك فقط، والسبب أن المرسل يستطيع أن يضع في رسالته ترويسة مزيفة تقولspf=pass.RejectFailures trueيرفض الرسالة فعلاً عندما تكون سياسة نطاق المرسلp=rejectوتفشل الرسالة، وبدونه يكتفي OpenDMARC بكتابة النتيجة. ولاحظ أن الرسائل المحولة Forwarded وبعض القوائم البريدية Mailing Lists قد تفشل في DMARC لأنها تغير الرسالة، فإذا لاحظت رفضاً لرسائل مشروعة من قائمة بريدية فاجعلهاfalse.RequiredHeaders trueيرفض الرسائل المشوهة التي لا تحمل ترويسة From واحدة أو Date واحدة كما يشترط معيار الرسائل، وهي غالباً رسائل مزعجة.IgnoreAuthenticatedClients trueيتجاوز رسائل مستخدميك على المنفذ 587، فهي لم توقع بعد عند وصولها إلى OpenDMARC.
تشغيل الخدمات والتحقق من الإعداد
الآن تحقق من إعداد Postfix، فإذا لم يطبع الأمر postfix check شيئاً فالإعداد سليم، ثم أعد تشغيل كل الخدمات:
sudo postfix check
sudo systemctl restart opendkim opendmarc dovecot postfix
sudo systemctl --no-pager status postfix dovecot opendkim opendmarc | grep -E "●|Active:"
sudo ss -tlnp | grep -E ":(25|587|993|8891|8893) "وفي مخرج ss سوف ترى المنافذ 25 و587 و993 على كل العناوين، والمنفذين 8891 و8893 على 127.0.0.1 فقط:
LISTEN 0 100 0.0.0.0:993 0.0.0.0:* users:(("dovecot",pid=277,fd=36))
LISTEN 0 100 0.0.0.0:587 0.0.0.0:*
LISTEN 0 100 0.0.0.0:25 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:8891 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:8893 0.0.0.0:*وكل ما يحدث بعد ذلك يسجل في /var/log/mail.log، فافتح نافذة ثانية وتابعه أثناء الاختبار:
sudo tail -f /var/log/mail.logالاختبار: إرسال واستقبال وقراءة
الإرسال عبر المنفذ 587
الأداة swaks تتحدث SMTP مثل برنامج البريد تماماً وتعرض كل سطر في الحوار، لذلك هي أفضل أداة للاختبار. نفذ الأمر التالي من جهازك أو من السيرفر نفسه، وضع مكان [email protected] حساباً خارجياً تملكه، ولاحظ أننا لم نكتب كلمة المرور في الأمر، فسوف يسألك عنها swaks ولا يظهرها على الشاشة بسبب --protect-prompt، ولا يطبعها في الحوار بسبب --auth-hide-password:
swaks --server mail.example.com --port 587 --tls \
--auth LOGIN --auth-user [email protected] --protect-prompt --auth-hide-password \
--from [email protected] --to [email protected] \
--header "Subject: Test from example.com" --body "Hello from Postfix and Dovecot"والمخرج سوف يكون كما يلي (أهم الأسطر):
<- 220 mail.example.com ESMTP
-> EHLO mx.example.net
<- 250-STARTTLS
-> STARTTLS
<- 220 2.0.0 Ready to start TLS
=== TLS started with cipher TLSv1.3:TLS_AES_256_GCM_SHA384:256
~> EHLO mx.example.net
<~ 250-AUTH PLAIN LOGIN
<~ 235 2.7.0 Authentication successful
~> MAIL FROM:<[email protected]>
<~ 250 2.1.0 Ok
<~ 250 2.1.5 Ok
<~ 250 2.0.0 Ok: queued as DA5CC1AC347في المخرج أعلاه لاحظ التالي: السيرفر لم يعلن AUTH في قائمة الأوامر الأولى، وإنما أعلنه فقط بعد STARTTLS، وهذا أثر smtpd_tls_auth_only. وفي السجل سوف ترى الرسالة تمر بكل المراحل، من تسجيل الدخول إلى التوقيع إلى التسليم:
postfix/submission/smtpd[817]: DA5CC1AC347: client=mx.example.net[198.51.100.25], sasl_method=LOGIN, [email protected]
opendkim[383]: DA5CC1AC347: DKIM-Signature field added (s=mail, d=example.com)
postfix/qmgr[808]: DA5CC1AC347: from=<[email protected]>, size=483, nrcpt=1 (queue active)
postfix/smtp[824]: DA5CC1AC347: to=<[email protected]>, relay=mx.example.net[198.51.100.25]:25, delay=0.18, delays=0.12/0.02/0.01/0.03, dsn=2.0.0, status=sent (250 OK)وإذا أرسلت إلى حساب في Gmail فافتح الرسالة واختر Show original، وتأكد أن نتيجة SPF وDKIM وDMARC هي PASS، وللتقييم الكامل أرسل رسالة إلى أداة مثل mail-tester.com التي تعطيك درجة من 10 مع سبب كل نقطة مخصومة. وإذا أردت أن تتحقق من التوقيع بنفسك، فاحفظ الرسالة كما وصلت (في Gmail: Download original) ثم افحصها بالأداة dkimverify من الحزمة python3-dkim، فهي تجلب المفتاح العام من DNS وتعيد حساب التوقيع:
sudo apt install python3-dkim
dkimverify < original_msg.emlsignature okالاستقبال عبر المنفذ 25 والقراءة عبر IMAP
أرسل الآن رسالة إلى [email protected] من حساب خارجي، أو من سيرفر آخر تملكه بالأداة swaks على المنفذ 25 دون كلمة مرور، كما يفعل أي سيرفر بريد في العالم:
swaks --server mail.example.com --port 25 --from [email protected] --to [email protected]وفي سجل سيرفرك سوف ترى الرسالة تمر بكل حارس من الحراس الذين أعددناهم بالترتيب: postscreen ثم فحص SPF ثم OpenDKIM ثم OpenDMARC ثم التسليم إلى Dovecot، والسطور التالية لرسالة من نطاق يوقع رسائله بـ DKIM:
postfix/postscreen[833]: CONNECT from [198.51.100.25]:33866 to [203.0.113.10]:25
postfix/postscreen[833]: PASS NEW [198.51.100.25]:33866
policyd-spf[838]: : prepend Authentication-Results: mail.example.com; spf=pass (sender SPF authorized) smtp.mailfrom=example.net (client-ip=198.51.100.25; helo=mx.example.net; [email protected]; receiver=example.com)
opendkim[383]: 9199B1AC2C7: DKIM verification successful
opendkim[383]: 9199B1AC2C7: s=s1 d=example.net a=rsa-sha256 SSL
opendmarc[898]: 9199B1AC2C7: example.net pass
dovecot: lmtp([email protected])<849><QJhLMqC5wmpRAwAAYIgGOA>: msgid=<[email protected]>: saved mail to INBOX
postfix/lmtp[848]: 9199B1AC2C7: to=<[email protected]>, relay=mail.example.com[private/dovecot-lmtp], delay=0.52, delays=0.17/0.03/0.06/0.26, dsn=2.0.0, status=sent (250 2.0.0 <[email protected]> QJhLMqC5wmpRAwAAYIgGOA Saved)تأكد بعد ذلك أن IMAP يعمل عبر TLS، فالأمر التالي يتصل بالمنفذ 993 ويطبع تحية Dovecot ثم يخرج:
printf "a1 LOGOUT\r\n" | openssl s_client -connect mail.example.com:993 -quiet 2>/dev/null* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ AUTH=PLAIN AUTH=LOGIN] Dovecot (Ubuntu) ready.
* BYE Logging out
a1 OK Logout completed.ثم اقرأ الرسالة كما يقرؤها برنامج البريد، والسكربت التالي بلغة Python يسجل الدخول عبر IMAP ويطبع ترويسات النتائج لكل رسالة في الصندوق:
import imaplib, ssl, getpass
M = imaplib.IMAP4_SSL("mail.example.com", 993, ssl_context=ssl.create_default_context())
M.login("[email protected]", getpass.getpass())
M.select("INBOX")
typ, data = M.search(None, "ALL")
for num in data[0].split():
typ, msg = M.fetch(num, "(BODY.PEEK[HEADER.FIELDS (AUTHENTICATION-RESULTS FROM SUBJECT)])")
print(msg[0][1].decode())
M.logout()والمخرج لرسالة موقعة من example.net سوف يكون كما يلي:
Authentication-Results: mail.example.com; dmarc=pass (p=reject dis=none) header.from=example.net
Authentication-Results: mail.example.com;
dkim=pass (2048-bit key; unprotected) header.d=example.net [email protected] header.a=rsa-sha256 header.s=s1 header.b=vei0flL0;
dkim-atps=neutral
Authentication-Results: mail.example.com; spf=pass (sender SPF authorized) smtp.mailfrom=example.net (client-ip=198.51.100.25; helo=mx.example.net; [email protected]; receiver=example.com)
From: Alice <[email protected]>
Subject: Hello from example.netفي المخرج أعلاه لاحظ التالي: كل حارس كتب نتيجته في ترويسة Authentication-Results مستقلة تبدأ باسم سيرفرك، وتقرأ من الأسفل إلى الأعلى بترتيب حدوثها: SPF أولاً ثم DKIM ثم DMARC الذي بنى قراره على الاثنين. وهذه الترويسات نفسها هي ما تقرؤه في Gmail عندما تختار Show original، فإذا وصلتك رسالة مشبوهة يوماً فهذا أول مكان تنظر فيه. ويستطيع المستخدم الآن إضافة الحساب في Thunderbird أو الهاتف بهذه القيم: IMAP على mail.example.com بالمنفذ 993 مع SSL/TLS، وSMTP بالمنفذ 587 مع STARTTLS، واسم المستخدم هو العنوان الكامل.
ماذا لو حاول أحدهم انتحال نطاقك؟
الإعداد الذي يعمل في الحالة الطبيعية نصف الاختبار فقط، والنصف الآخر أن تتأكد أنه يرفض ما يجب رفضه. لذلك سوف نتصرف الآن كالمخترق من سيرفر آخر، ونجرب الحيل المعروفة واحدة واحدة، ونرى كيف يردها كل حارس.
أولاً: رسالة على المنفذ 25 عنوان مغلفها [email protected] من سيرفر ليس في سجل SPF لنطاقك:
swaks --server mail.example.com --from [email protected] --to [email protected]<** 550 5.7.23 <[email protected]>: Recipient address rejected: Message rejected due to: SPF fail - not authorized. Please see http://www.openspf.net/Why?s=mfrom;[email protected];ip=198.51.100.25;r=example.comرفضها policyd-spf قبل أن تبدأ الرسالة نفسها، لأن سجلك يقول -all. فيحاول المخترق الحيلة الثانية: يضع نطاقه هو في المغلف حتى يجتاز SPF، ويضع نطاقك في From الظاهر:
swaks --server mail.example.com --from [email protected] --to [email protected] \
--header "From: CEO <[email protected]>" --header "Subject: urgent transfer"<** 550 5.7.1 rejected by DMARC policy for example.comاجتازت الرسالة SPF فعلاً، ولكن OpenDMARC لاحظ أن النطاق الظاهر example.com لا يطابق النطاق الذي اجتاز SPF ولا يوجد توقيع DKIM منه، فطبق سياسة p=reject المنشورة لنطاقك. ولاحظ أن هذا يحدث فقط بعد أن تنتقل بسياستك إلى reject، أما مع p=none فتمر الرسالة وتسجل النتيجة dmarc=fail، وهذا هو سبب الانتقال إلى reject بعد أن تراجع التقارير.
ثالثاً: رسالة موقعة توقيعاً صحيحاً، ثم عدل أحدهم جملة واحدة في جسمها في الطريق، فتصل مع النتيجة التالية:
Authentication-Results: mail.example.com;
dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=example.net [email protected] header.a=rsa-sha256 header.s=s1 header.b=vei0flL0;رابعاً: محاولة استخدام سيرفرك مرحلاً مفتوحاً إلى نطاق خارجي دون تسجيل دخول، ثم محاولة مستخدم مسجل أن يرسل باسم زميله، ثم كلمة مرور خاطئة، ثم محاولة المصادقة دون TLS:
<** 554 5.7.1 <[email protected]>: Relay access denied
<~* 553 5.7.1 <[email protected]>: Sender address rejected: not owned by user [email protected]
<~* 535 5.7.8 Error: authentication failed: (reason unavailable)
*** Host did not advertise authenticationوالأخير يعني أن السيرفر لم يعرض المصادقة أصلاً على اتصال غير مشفر. وأخيراً رسالة إلى عنوان غير موجود، فترفض أثناء الاتصال دون Backscatter:
<** 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown in virtual mailbox tableالحماية من الرسائل المزعجة وتخمين كلمات المرور
postscreen: حارس البوابة
معظم الرسائل المزعجة تأتي من برامج آلية مستعجلة لا تتبع بروتوكول SMTP بدقة، فلا تنتظر تحية السيرفر قبل أن تتكلم، أو ترسل عدة أوامر دفعة واحدة. والإعداد postscreen_greet_action = enforce يجعل postscreen ينتظر بضع ثوان قبل التحية، فإذا تكلم العميل قبلها سجل عليه مخالفة ورفض رسائله، وهذا ما يحدث مع برنامج آلي يرسل EHLO فوراً:
postfix/postscreen[833]: CONNECT from [192.0.2.30]:53736 to [203.0.113.10]:25
postfix/postscreen[833]: PREGREET 10 after 0 from [192.0.2.30]:53736: EHLO bot\r\n
postfix/postscreen[833]: NOQUEUE: reject: RCPT from [192.0.2.30]:53736: 550 5.5.1 Protocol error; from=<[email protected]>, to=<[email protected]>, proto=ESMTP, helo=<bot>والعميل الذي يجتاز الفحوص يحفظه postscreen في ذاكرة مؤقتة Cache فلا ينتظر في المرات التالية، وهذا معنى PASS NEW الذي رأيناه في الاختبار.
قوائم الحظر DNSBL ومحاذيرها
السطر postscreen_dnsbl_sites يسأل قوائم حظر عامة DNS Blocklists عن عنوان كل عميل، ويعطي كل قائمة وزناً، فإذا بلغ المجموع postscreen_dnsbl_threshold رفض العميل، وهنا يكفي ظهور العنوان في Spamhaus ZEN وحده (الوزن 3)، أما SpamCop فلا يكفي وحده (الوزن 2). ولكن هذه القوائم لها محاذير يجب أن تعرفها قبل أن تعتمد عليها:
- تمنع Spamhaus الاستعلام المجاني من خوادم DNS العامة مثل 8.8.8.8 و1.1.1.1 ومن خوادم كثير من المزودين، وترد عليها برموز خطأ مثل
127.255.255.254بدلاً من النتيجة. والخطير أن سيرفراً يعامل أي رد على أنه وجود في القائمة سوف يرفض البريد كله. - لذلك كتبنا الرموز المقبولة صراحة
zen.spamhaus.org=127.0.0.[2..11]، فلا يحسب postscreen إلا رموز الحظر الحقيقية، وتصبح رموز الخطأ بلا أثر. - وإذا كان سيرفرك يستخدم خادم DNS عاماً أو خادم مزود محظوراً، فلن تعمل Spamhaus، والحل أن تثبت خادم DNS محلياً مثل
unboundيستعلم مباشرة، أو أن تسجل في خدمة Spamhaus المجانية DQS وتستخدم نطاقها الخاص.
حدود المعدل Rate Limits
القيم smtpd_client_*_rate_limit تحدد عدد الاتصالات والرسائل والمستلمين لكل عنوان IP في الدقيقة، ويحسبها Postfix عبر خدمة anvil، ودليل الضبط يشرح كيف تختار القيم. ولاحظ أنها تطبق على عنوان IP وليس على المستخدم، فإذا سرق أحدهم كلمة مرور أحد مستخدميك وأرسل من عناوين كثيرة فلن توقفه هذه الحدود، وهذا ما تفعله fail2ban وكلمات المرور القوية، وإذا احتجت إلى حدود لكل مستخدم فهي من الأسباب الوجيهة للانتقال إلى Rspamd.
تهريب SMTP وإصلاحه
نهاية الرسالة في SMTP هي سطر فيه نقطة وحدها بين نهايتي سطر قياسيتين <CR><LF>.<CR><LF>، ولكن Postfix مثل غيره كان يقبل نهاية السطر غير القياسية <LF> وحدها، توافقاً مع برامج قديمة. واستغل باحثون هذا الاختلاف بين السيرفرات لتهريب رسالة مزيفة داخل رسالة حقيقية، والإعداد smtpd_forbid_bare_newline = normalize في main.cf يغلق هذا الباب.
fail2ban: إيقاف تخمين كلمات المرور
بعد أيام من تشغيل السيرفر سوف ترى في السجل محاولات دخول فاشلة على المنفذين 587 و993 من عناوين في كل مكان، فهذه برامج تجرب كلمات مرور شائعة على كل خادم بريد تجده. والحزمة fail2ban تقرأ السجل وتحظر العنوان في جدار الحماية بعد عدد من المحاولات الفاشلة، وفيها سجون جاهزة Jails لـ Postfix وDovecot، وكل ما علينا أن نفعلها:
sudo nano /etc/fail2ban/jail.d/mail.local[postfix-sasl]
enabled = true
backend = auto
logpath = /var/log/mail.log
maxretry = 5
findtime = 10m
bantime = 1h
[dovecot]
enabled = true
backend = auto
logpath = /var/log/mail.log
maxretry = 5
findtime = 10m
bantime = 1hsudo systemctl restart fail2ban
sudo fail2ban-client status postfix-saslوقبل أن تعتمد عليها تأكد أن فلاترها تطابق سطور السجل عندك فعلاً، فالأمر fail2ban-regex يمرر السجل على الفلتر ويعد المطابقات، وبعد محاولتي دخول فاشلتين على 587 ومحاولة على 993 سوف ترى:
sudo fail2ban-regex /var/log/mail.log "postfix[mode=auth]" | grep -E "^Lines"
sudo fail2ban-regex /var/log/mail.log dovecot | grep -E "^Lines"Lines: 183 lines, 0 ignored, 2 matched, 181 missed
Lines: 184 lines, 0 ignored, 1 matched, 183 missedولاحظ أن Ubuntu 24.04 يجعل الطريقة الافتراضية لقراءة السجلات backend = systemd في الملف defaults-debian.conf، ولكننا حددنا للسجنين الملف /var/log/mail.log الذي يكتبه rsyslog، والسبب أن هذا هو الملف نفسه الذي نختبر عليه الفلتر بالأمر fail2ban-regex، فنضمن أن ما اختبرناه هو ما يعمل. وتأكد أيضاً أن عنوانك الثابت في ignoreip إذا كنت تخطئ في كلمة المرور كثيراً، حتى لا تحظر نفسك.
MTA-STS وTLS-RPT (اختياري)
الإعداد smtpd_tls_security_level = may يعني أن السيرفر المرسل يستخدم TLS إن استطاع، ولكن المخترق في منتصف الطريق يستطيع أن يحذف إعلان STARTTLS فيرسل السيرفر الرسالة دون تشفير. والمعيار MTA-STS يغلق ذلك، حيث تعلن فيه أن بريد نطاقك يجب أن يصل عبر TLS بشهادة صالحة فقط، فتلتزم بذلك السيرفرات التي تدعمه مثل Gmail. ويحتاج إلى ثلاثة أشياء: ملف سياسة على https://mta-sts.example.com/.well-known/mta-sts.txt يقدمه أي خادم ويب بشهادة صالحة، وسجلي TXT:
version: STSv1
mode: testing
mx: mail.example.com
max_age: 86400
| الاسم | النوع | القيمة |
|---|---|---|
_mta-sts.example.com | TXT | v=STSv1; id=20261004 |
_smtp._tls.example.com | TXT | v=TLSRPTv1; rua=mailto:[email protected] |
السجل الثاني هو TLS-RPT، وبه تصلك تقارير يومية عن فشل TLS عند السيرفرات الأخرى، فأضف [email protected] إلى ملف virtual. وابدأ بالوضع testing وراجع التقارير، ثم انتقل إلى enforce، وغير قيمة id في كل مرة تعدل فيها ملف السياسة حتى تعرف السيرفرات أنه تغير.
النسخ الاحتياطي والاستعادة
خادم البريد هذا كله ملفات، وهذه ميزة كبيرة عند النسخ الاحتياطي Backup، فلا توجد قاعدة بيانات تحتاج إلى أداة خاصة. والمهم أن تنسخ ثلاثة أشياء: الرسائل في /var/vmail، والإعداد في /etc، ومفاتيح DKIM، والسبب أن خسارة المفتاح الخاص تعني أن تنشئ مفتاحاً جديداً وتغير سجل DNS، وخلال ذلك تفشل كل رسائلك في DKIM:
sudo tar czf /root/mail-backup-$(date +%F).tar.gz -C / \
var/vmail etc/postfix etc/dovecot etc/opendkim etc/opendkim.conf etc/opendmarc.conf \
etc/postfix-policyd-spf-python etc/fail2ban/jail.d/mail.local etc/letsencryptنسخ Maildir والخدمات تعمل آمن، والسبب أن Dovecot يكتب كل رسالة في ملف مؤقت ثم ينقله إلى مكانه دفعة واحدة، فلا تجد في النسخة رسالة نصف مكتوبة، وأسوأ ما يحدث أن ملفات الفهرس Index تحتاج إلى إعادة بناء فيعيد Dovecot بناءها تلقائياً. ولكن تذكر أن النسخة على قرص السيرفر نفسه لا تحميك إذا تعطل السيرفر، لذلك انقلها يومياً إلى تخزين خارجي Offsite Storage بأداة مثل restic أو rsync، واحذف النسخ المحلية القديمة. وللجدولة اليومية أضف مهمة cron:
sudo crontab -e30 2 * * * tar czf /root/mail-backup-$(date +\%F).tar.gz -C / var/vmail etc/postfix etc/dovecot etc/opendkim etc/opendkim.conf etc/opendmarc.conf etc/postfix-policyd-spf-python etc/fail2ban/jail.d/mail.local etc/letsencrypt && find /root -name 'mail-backup-*.tar.gz' -mtime +7 -deleteوللاستعادة Restore على سيرفر جديد ثبت الحزم نفسها على الإصدار نفسه من Ubuntu، وأنشئ المستخدم vmail بالرقم 5000 كما فعلنا، ثم أوقف الخدمات وفك النسخة وأعد تشغيلها:
sudo systemctl stop postfix dovecot opendkim opendmarc
sudo tar xzf mail-backup-2026-10-04.tar.gz -C /
sudo chown -R vmail:vmail /var/vmail
sudo postmap /etc/postfix/vmailbox /etc/postfix/virtual /etc/postfix/sender_login
sudo systemctl start opendkim opendmarc dovecot postfixوإذا كنت تنقل البريد من سيرفر آخر وليس من نسخة احتياطية، فطريقة imapsync التي شرحناها في دليل ترحيل البريد بين خادمي mailcow تعمل هنا أيضاً، لأنها تتحدث IMAP مع الطرفين ولا تهتم بما خلفهما.
التحديث إلى إصدار أحدث
كل المكونات هنا حزم من Ubuntu، فتحديثها هو تحديث النظام نفسه، وتطبق unattended-upgrades المثبتة افتراضياً التحديثات الأمنية تلقائياً، وتستطيع أن تحدث يدوياً وتعيد تشغيل الخدمات:
sudo apt update
sudo apt upgrade
sudo postfix check
sudo systemctl restart postfix dovecot opendkim opendmarcأما الترقية إلى إصدار Ubuntu التالي فتحتاج إلى تخطيط، والسبب أن Ubuntu 26.04 يأتي بالإصدار Dovecot 2.4، وقد تغيرت فيه صيغة الإعداد تغييراً كبيراً، فكثير من الإعدادات في الملف الذي كتبناه تغير اسمها أو طريقة كتابتها، ولن يعمل Dovecot بالملف القديم بعد الترقية. لذلك لا تقم بالترقية على سيرفر الإنتاج مباشرة، بل جهز سيرفراً جديداً بالإصدار الجديد واكتب عليه إعداد Dovecot بالصيغة الجديدة، ثم انقل البريد إليه بالنسخة الاحتياطية.
مشكلات شائعة وحلولها
كل مشكلة في هذا الإعداد تترك سطراً في /var/log/mail.log، ومعرفة السطر نصف الحل. وإذا احتجت إلى تفاصيل أكثر من مكون محدد فاتبع دليل التشخيص في Postfix، وفيما يلي أكثر السطور التي سوف تراها ومعناها.
connect to …:25: Connection timed out
postfix/smtp[2190]: connect to mx.example.net[198.51.100.25]:25: Connection timed outإذا ظهر سطر بهذا الشكل فالرسائل الصادرة تبقى في الطابور Queue ولا تخرج، والسبب في الغالب أن المزود يحجب المنفذ 25 الصادر، فتأكد بالأمر التالي من السيرفر نفسه، وإذا انتهت المهلة دون اتصال فاطلب فتح المنفذ من الدعم الفني:
nc -vz -w 5 gmail-smtp-in.l.google.com 25
sudo postqueue -pوإذا رفض المزود فتحه، فالحل أن ترسل عبر خادم وسيط SMTP Relay مثل Amazon SES بالإعداد relayhost، وأضف الوسيط إلى سجل SPF ووقع رسائلك بـ DKIM كما هي.
warning: connect to Milter service … Connection refused
OpenDKIM أو OpenDMARC متوقف، وبسبب milter_default_action = accept تمر الرسائل دون توقيع ودون فحص، فلن تلاحظ المشكلة إلا عندما تفشل رسائلك في DKIM. راجع حالة الخدمة وسجلها بالأمر systemctl status opendkim، وأكثر الأسباب شيوعاً خطأ في صلاحيات ملف المفتاح أو خطأ كتابي في opendkim.conf.
Relay access denied
إذا ظهر لمستخدم يرسل من برنامجه، فهو يرسل على المنفذ 25 أو دون تسجيل دخول، فاضبط في برنامجه المنفذ 587 مع STARTTLS واسم المستخدم الكامل. وإذا ظهر لسيرفر خارجي يرسل إلى نطاقك، فالنطاق ليس في virtual_mailbox_domains.
SASL LOGIN authentication failed
كلمة المرور خاطئة، أو أن الهاش في /etc/dovecot/users نسخ ناقصاً، فاختبر بالأمر doveadm auth test مباشرة. وإذا ظهر في السجل warning: SASL: Connect to private/auth failed: No such file or directory، فالمقبس غير موجود لأن Dovecot متوقف أو أن مسار unix_listener في إعداده لا يطابق smtpd_sasl_path.
الرسالة مقبولة ولكنها لا تصل إلى الصندوق
ابحث عن رقم الرسالة في السجل، فإذا ظهر سطر postfix/lmtp مع status=deferred فالمشكلة بين Postfix وDovecot. والسبب الأشهر أن المقبس private/dovecot-lmtp لا يملكه المستخدم postfix، أو أن صلاحيات /var/vmail لا تسمح لـ vmail بالكتابة. وإذا ظهر User doesn't exist فالعنوان موجود في vmailbox وليس في /etc/dovecot/users.
milter-reject: END-OF-MESSAGE … 5.7.1 Command rejected
opendmarc[328]: 798D11AC353: RFC5322 requirement error: not exactly one Date field
postfix/cleanup[823]: 798D11AC353: milter-reject: END-OF-MESSAGE from mx.example.net[198.51.100.25]: 5.7.1 Command rejected; from=<[email protected]> to=<[email protected]>رفض OpenDMARC الرسالة لأنها مشوهة، والسطر الذي قبله يقول السبب: لا توجد ترويسة Date. وهذا يحدث كثيراً مع السكربتات والأجهزة التي ترسل البريد بنفسها مثل الطابعات وأنظمة المراقبة، فأصلح المرسل حتى يضيف الترويسات القياسية، أو اجعل RequiredHeaders false إذا لم تستطع.
رسائلي تصل إلى مجلد الرسائل المزعجة
- افتح الرسالة في Gmail واختر Show original، فإذا كانت نتيجة DKIM
failأوnoneفالمفتاح في DNS ناقص أو بمسافات زائدة، فقارنه بالأمرopendkim-testkey. - تأكد أن
dig +short -x 203.0.113.10يعيدmail.example.com، وأن السجل A لهذا الاسم يعيد العنوان نفسه. - السيرفر الجديد ليس له تاريخ إرسال، فالسيرفرات الكبيرة تعامله بحذر، لذلك ابدأ بحجم صغير ولا ترسل منه حملات تسويقية، بل خصص لها أداة مستقلة مثل listmonk مع خدمة إرسال ونطاق فرعي Subdomain، والسبب أن شكاوى حملة واحدة قد تضر بريد فريقك اليومي.
- افحص عنوانك في قوائم الحظر، واطلب رفعه منها إذا وجدته، ولخدمات Microsoft سجل عنوانك في Microsoft SNDS.
الخلاصة
وصلنا لنهاية الموضوع، وأهم ما فيه:
- خادم البريد مكونات منفصلة: Postfix ينقل البريد، وDovecot يخزنه ويقدمه ويتحقق من كلمات المرور، وpolicyd-spf وOpenDKIM وOpenDMARC يفحصون الرسائل ويوقعونها، وكل مكون يكتب ما فعله في
/var/log/mail.log. - Postfix وحده يرسل، ولكن رسائله تصل إلى الرسائل المزعجة، لذلك اضبط PTR وSPF وDKIM وDMARC قبل أول رسالة، وابدأ DMARC بالقيمة
p=noneثم انتقل إلىreject. - استخدم صناديق افتراضية يملكها مستخدم واحد لا يستطيع الدخول، وكلمات مرور ARGON2ID، ولا تقبل كلمة مرور إلا على 587 و993 بعد TLS.
- جرب الرفض كما جربت القبول: انتحال المغلف، وانتحال From، والمرحل المفتوح، والإرسال باسم زميل.
- فعل
smtpd_forbid_bare_newlineوfail2ban، وانسخ/var/vmailومفاتيح DKIM والإعداد إلى تخزين خارجي مشفر، ولا ترق إلى Ubuntu 26.04 دون إعادة كتابة إعداد Dovecot للإصدار 2.4.
وإذا أردت أن تبني خادم البريد نفسه في برنامج واحد يجمع هذه المكونات فاقرأ دليل تثبيت Stalwart، ولتختار بين الطرق الثلاث: البناء اليدوي وmailcow وStalwart، اقرأ مقارنة خوادم البريد ونقاط القوة ونقاط الضعف في كل منها.
تدريب عملي
- أضف صندوقاً ثانياً
[email protected]في الملفين، ثم أرسل منه بحسابinfoولاحظ رسالة الرفض، ثم أضف السطر المناسب فيsender_loginحتى يرسلinfoباسمsales. - أوقف OpenDKIM مؤقتاً وأرسل رسالة إلى Gmail، ثم قارن Show original مع رسالة أرسلتها وهو يعمل، وابحث في السجل عن السطر الذي يخبرك بالمشكلة.
سجل التحديثات
- أكتوبر 2026: كتابة الدليل واختباره على Ubuntu 24.04 مع Postfix 3.8.6 وDovecot 2.3.21 وOpenDKIM 2.11.0~beta2 وOpenDMARC 1.4.2 وpolicyd-spf 3.0.4.