يتميز Redis بالسرعة لأنه يثق بعملائه. ويقول توثيق أمان Redis ذلك بوضوح: صُمّم Redis ليصل إليه عملاء موثوقون داخل بيئات موثوقة، ولا ينبغي كشفه مباشرة على الإنترنت. فالنسخة المكشوفة يمكن مسح بياناتها بأمر FLUSHALL واحد، والعميل الذي يستطيع تنفيذ CONFIG يمكنه أن يجعل Redis يكتب ملفات في مسارات عشوائية، مما قد يؤدي إلى تشغيل شيفرة بصلاحيات مستخدم Redis. يتناول هذا الدليل الطبقات التي تحمي خادم Redis على VPS.
الطبقة الأولى: أبعِده عن الشبكة
إذا كان Redis والتطبيق يعملان على الخادم نفسه، فيجب أن يستمع Redis على عنوان loopback فقط. وملف redis.conf النموذجي من المشروع في الإصدارين 7.0 و8.0 يفعل ذلك أصلاً ويُبقي وضع الحماية مفعّلاً:
# /etc/redis/redis.conf on Debian and Ubuntu
bind 127.0.0.1 -::1
protected-mode yes
port 6379منذ الإصدار 3.2 يجعل وضع الحماية النسخةَ التي تستمع على كل الواجهات ودون كلمة مرور لا تجيب إلا عبر loopback، وترسل رسالة خطأ لغيرها. لكنه شبكة أمان وليس إعداداً كافياً، إذ يستطيع المسؤول تعطيله أو ربط Redis بكل الواجهات. تحقق مما يستمع فعلاً:
sudo ss -tlnp | grep 6379ينبغي أن ترى 127.0.0.1:6379 و[::1]:6379، وليس 0.0.0.0:6379 أبداً. وإذا كان التطبيق على خادم آخر فاربط Redis بعنوان خاص، واسمح بالمنفذ 6379 من خوادم التطبيق فقط في جدار الحماية على الخادم وفي أي جدار حماية سحابي، وأضف TLS (الطبقة الرابعة).
الطبقة الثانية: مستخدمون حقيقيون بدلاً من المستخدم الافتراضي المفتوح
يأتي Redis افتراضياً بمستخدم واحد اسمه default، ويعرضه توثيق ACL بالشكل user default on nopass ~* &* +@all؛ أي أن كل اتصال يُصادَق عليه تلقائياً ويستطيع تنفيذ كل الأوامر على كل المفاتيح. ومنذ Redis 6 أصبحت قوائم التحكم في الوصول (ACL) هي الطريقة الموصى بها للمصادقة، أما الإعداد القديم requirepass فيضع كلمة مرور لذلك المستخدم الافتراضي فقط.
والإعداد العملي هو تعطيل المستخدم الافتراضي وتعريف مستخدمين بأسماء في ملف ACL خارجي:
# /etc/redis/redis.conf
aclfile /etc/redis/users.acl
# /etc/redis/users.acl
user default off
user app on >REPLACE-WITH-LONG-RANDOM-PASSWORD ~app:* &* +@all -@dangerous
user admin on >REPLACE-WITH-ANOTHER-PASSWORD ~* &* +@all# generate passwords, protect the file, restart
openssl rand -base64 32
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 640 /etc/redis/users.acl
sudo systemctl restart redis-serverنقاط مهمة من التوثيق:
- لا يمكن الجمع بين مستخدمين معرّفين في
redis.confوملف ACL خارجي، وإلا رفض Redis العمل. كما يُتجاهلrequirepassعند استخدامaclfile. - بعد تعديل الملف يعيد الأمر
ACL LOADتحميله، بشرط أن تكون كل أسطر المستخدمين صحيحة، وإلا بقي الإعداد القديم فعّالاً. - بدلاً من كلمة المرور الصريحة
>passwordيمكن أن يحتوي السطر على#متبوعة ببصمة SHA-256 لكلمة المرور، فلا يحتوي الملف على كلمة المرور نفسها. - يجب أن تكون كلمات المرور طويلة، فسرعة Redis تسمح للمهاجم بتجربة كلمات مرور كثيرة في الثانية.
اختبر الإعداد:
redis-cli
127.0.0.1:6379> PING # expect a NOAUTH error
127.0.0.1:6379> AUTH app the-password
127.0.0.1:6379> ACL WHOAMIالطبقة الثالثة: أبعِد الأوامر الخطرة عن التطبيق
تشمل فئة ACL المسماة dangerous أوامر مثل FLUSHALL وCONFIG وDEBUG وKEYS وSORT وCLIENT وINFO وSAVE وREPLICAOF وغيرها. وإزالتها من مستخدم التطبيق (-@dangerous) تعني أن خطأً برمجياً أو حقناً في التطبيق لا يستطيع إعادة ضبط Redis. وبعض أطر العمل تستدعي INFO أو KEYS؛ فإن كان إطارك منها فأعد ذلك الأمر وحده، مثل +info، ثم اختبر.
ما يزال التوجيه القديم rename-command يعمل لكنه مهمل، ويوصي التوثيق بقواعد ACL بدلاً منه. كما يأتي Redis 7.0 وما بعده بثلاثة إعدادات تمنع الميزات الخطرة افتراضياً: يُبقي enable-protected-configs الإعدادات المتعلقة بالملفات مثل dir وdbfilename غير قابلة للتغيير أثناء التشغيل، ويمنع enable-debug-command وenable-module-command الأمرين DEBUG وMODULE. اتركها على قيمتها الافتراضية no ما لم تكن لديك حاجة محددة، وعندها فضّل القيمة local.
الطبقة الرابعة: TLS عندما تغادر الحركة الخادم
يُرسل الأمر AUTH نصاً صريحاً مثل أي أمر آخر، لذا يمكن لمن يراقب الشبكة بين الخوادم قراءة بيانات الدخول والبيانات نفسها. ويدعم Redis بروتوكول TLS منذ الإصدار 6 كخيار عند البناء (توثيق TLS في Redis). ومع نسخة مبنية بدعم TLS يبدو المستمع المقتصر على TLS هكذا:
port 0
tls-port 6379
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crtافتراضياً يجب على العملاء تقديم شهادة أيضاً، ويلغي الخيار tls-auth-clients no ذلك. ويتصل العملاء عبر redis-cli --tls --cacert ... مع شهادتهم الخاصة إن لزم الأمر. أما على خادم واحد فالربط بعنوان loopback أبسط ويكفي.
شغّله دون صلاحيات وحافظ على تحديثه
لا يحتاج Redis إلى صلاحيات الجذر، ويوصي التوثيق بتشغيله بمستخدم مخصص غير مميز؛ تحقق من ذلك بالأمر ps -o user= -C redis-server. ويأتي Debian 12 (bookworm) بالإصدار 7.0.15 من Redis ويأتي Debian 13 (trixie) بالإصدار 8.0.2 بحسب متتبع الحزم، ويتلقى كلاهما الإصلاحات الأمنية عبر نشرات Debian. تابع صفحة redis في متتبع أمان Debian، وثبّت التحديثات بالأمر sudo apt update && sudo apt upgrade، ثم أعد تشغيل redis-server، لأن العملية العاملة تحتفظ بالشيفرة القديمة إلى ذلك الحين.
أخطاء شائعة
- تغيير
bindإلى0.0.0.0«لإصلاح» خطأ اتصال من خادم آخر دون جدار حماية أو كلمة مرور. - نشر Redis من حاوية Docker بالخيار
-p 6379:6379، فيُربط بكل الواجهات ولا يغطيه ufw. - وضع كلمة مرور مع ترك المستخدم الافتراضي بصلاحية
+@allللتطبيق. - ترك ملفات RDB أو AOF، وهي تحتوي على كل البيانات، قابلة للقراءة من مستخدمين آخرين أو منسوخة إلى نسخ احتياطية غير محمية.
ما الذي ينبغي فعله
- شغّل
ss -tlnp | grep 6379على كل خادم وتأكد من أن Redis يستمع فقط حيث يجب. - عطّل المستخدم
defaultوأنشئ مستخدمي ACL بأسماء وكلمات مرور طويلة وبالمفاتيح التي يحتاجونها فقط. - أزل فئة
@dangerousمن مستخدمي التطبيق، وأبقِ إعدادات الحماية على القيمةno. - استخدم TLS وقواعد جدار الحماية لأي حركة Redis بين الخوادم.
- تابع التحديثات الأمنية لـ Redis في إصدارك وأعد تشغيل الخدمة بعد تثبيتها.
المصادر
- redis.io/docs/latest/operate/oss_and_stack/management/security
- redis.io/docs/latest/operate/oss_and_stack/management/security/acl
- redis.io/docs/latest/operate/oss_and_stack/management/security/encryption
- raw.githubusercontent.com/redis/redis/8.0/redis.conf
- raw.githubusercontent.com/redis/redis/7.0/redis.conf
- redis.io/docs/latest/develop/tools/cli
- packages.ubuntu.com/noble/amd64/redis-server/filelist
- git.launchpad.net/ubuntu/+source/redis/plain/redis.conf?h=applied/ubuntu/noble
- tracker.debian.org/pkg/redis
- security-tracker.debian.org/tracker/source-package/redis
Comments
0 total · 0 threads