في كل مرة نقوم فيها بالاتصال عبر بروتوكول ssh بالخادم ، يتحقق عميل ssh لمعرفة ما إذا كان المفتاح العام لهذا الخادم يطابق آخر مرة (على الأقل يوصي بإجراء معيار ssh). في OpenSSH ، يتم تخزين قائمة مفاتيح الخادم المعروفة في ملف known_hosts. تحت katom لفترة وجيزة حول ما وكيف يتم تخزينها بالضبط هناك.
أجريت جميع التجارب على لينكس (Debian / Mint / Ubuntu). لا أستطيع أن أضمن موقع ومحتويات الملفات في أنظمة تشغيل أخرى.عند الاتصال بخادم ssh لأول مرة ، نرى شيئًا مثل هذا:
لا يمكن إثبات صحة المضيف "192.168.0.2 (192.168.0.2)".
بصمة مفتاح RSA هي SHA256: kd9mRkEGLo + RBBNpxKp7mInocF3 / Yl / 0fXRsGJ2JfYg.
هل أنت متأكد من أنك تريد الاستمرار في الاتصال (نعم / لا)؟
إذا وافقت ، ستتم إضافة السطر التالي إلى ملف ~ / .ssh / known_hosts:
| 1 | CuXixZ + EWfgz40wpkMugPHPalyk = | KNoVhur7z5NAZmNndtwWq0kN1SQ = سه-آر إس إيه AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh / e4q91 + + عز i9S0s3M2LPq + GAhRlhKt5vKyEVd6x6m26cc98Y + SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x + mPvO9FLSBk / Al2GbH5q6F + hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd + c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti + 7xGwT8DF + tIyLFcU + zxd0QnwJIbNvewkHs0LsMOWFVPz / Nd0XiVXimX + ugCDBZ / 4q8NUwH9SGzCMAvnnr + D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV
هنا ، يتم كتابة ثلاثة عناصر بمسافة: تجزئة نيابة عن الخادم واسم الخوارزمية غير المتماثلة المستخدمة والمفتاح العام للخادم. دعنا ننفصل بينهما.
وإذا قرأت التعليماتفي الواقع ، وفقًا
لدليل Ubunt ، يمكن أن يكون هناك
حقلين إضافيين ، مفصولين أيضًا بمسافات:
- في بداية السطر ، قد تكون هناك ملاحظة "@ cert-Authority" أو "revoked" ، مما يعني ، على التوالي ، أن المفتاح العام للمرجع المصدق مكتوب في هذا السطر أو أنه تم إبطال هذا المفتاح ولا يمكن استخدامه.
- قد يكون هناك تعليق تعسفي في نهاية السطر
اسم الخادم
في المثال ، تبدو التجزئة نيابة عن الخادم (المضيف) كما يلي:
| 1 | CuXixZ + EWfgz40wpkMugPHPalyk = | KNoVhur7z5NAZmNndtwWq0kN1SQ =
في الواقع ، يمكن كتابة اسم المضيف في نص واضح أو قناع يحدد مجموعة من الأسماء الصالحة هنا. ولكن يتم حفظ اسم التجزئة الافتراضي الخاص بي. السجل مقسم إلى 3 أجزاء بالرمز "|". الجزء الأول هو خوارزمية التجزئة. "1" يتوافق مع HMAC-SHA1 (لم أر الآخرين). الجزء الثاني هو الملح (مفتاح HMAC). الجزء الثالث هو التجزئة نفسها (إخراج HMAC).
تحققfrom base64 import b64decode import hmac salt = b64decode("CuXixZ+EWfgz40wpkMugPHPalyk=") host = b'192.168.0.2' hash = hmac.HMAC(salt, host, 'sha1').digest() print(b64encode(hash).decode())
> 'KNoVhur7z5NAZmNndtwWq0kN1SQ ='
خوارزمية غير متماثلة
يسرد
RFC-4253 4 خوارزميات غير متماثلة: ssh-dss (إلزامي حسب المعيار ، لكنه يعتبر ضعيفًا ويتم إيقافه افتراضيًا منذ OpenSSH7.0) ، ssh-rsa (مستحسن) ، pgp-sign-rsa (اختياري) ، pgp- تسجيل dss (اختياري). بشكل افتراضي ، يتم إنشاء مفاتيح النوعين الأولين في Linux لخوارزميات المنحنى البيضاوي غير المذكورة في RFC. يفضل هذا الأخير ، ولكن يمكن للعميل تحديد الخوارزمية باستخدام خيار HostKeyAlgorithms.
كيفية التحقق من بصمة المفتاح المطلوب (وليس الافتراضي)يمكن أن يكون هذا مفيدًا ، على سبيل المثال ، عندما تدخل الخادم لأول مرة إذا كنت تريد التحقق من بصمة المفتاح ، وكنت تعرف فقط بصمة مفتاح ssh-rsa. ثم يمكنك الاتصال بهذا الأمر:
ssh root@192.168.0.2 -o HostKeyAlgorithms = ssh-rsa
إذا كنت بحاجة أيضًا إلى تحديد خوارزمية التجزئة الرئيسية ، يمكنك استخدام خيار FingerprintHash. على سبيل المثال ، إذا كان md5 فقط معروفًا من ssh-rsa ، فيمكنك الاتصال مثل هذا:
ssh root@192.168.0.2 -o HostKeyAlgorithms = ssh-rsa -o FingerprintHash = md5
مفتاح عام
المفتاح العام في known_hosts هو نفس المفتاح المسجل في ملف /etc/ssh/ssh_host_rsa_key.pub على الخادم (استبدل اسم الخوارزمية المستخدمة بدلاً من rsa). إذا قمت بإزالة ترميز Base64 ، فسيكون في الداخل مرة أخرى اسم الخوارزمية والمكونات الرئيسية الفعلية.
لماذا لا تقم بإزالة Base64 b'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x03\x01\x00\x01\x00\x00\x01\x01\x00\x9e\x88^\x0e8\xe5!Z\xf3\x98\xae\x1f\xde\xe2\xafu\xfa,\xfe\x8b\xd4\xb4\xb3s6,\xfa\xbe\x18\x08Q\x96\x12\xad\xe6\xf2\xb2\x11Wz\xc7\xa9\xb6\xe9\xc7=\xf1\x8f\x92Ay\xc2\x07\xd1\x96yV$\xf29E\x1cE\xe7c\x86\x16yb\xc3\xc1r!\x1c\x12X\xb7\x9c\xb3\xde>V\x92\x0fy\xc7\xe9\x8f\xbc\xefE- d\xfc\tv\x19\xb1\xf9\xab\xa1~\x85\x92%.c\xbar"\x12\x99~\x13\xb5\xc1\xb5\xb3\x0e\x12\xc2\x84\xc0\x0e\xba\xe1t\xcd\x0e%\xdf\x9c\xe4%<\x8a\xa0\x9bs\xa3\xf3\x9d\x86\xcbep\xaf\xa8\xf6SY\xe4\x9bL\xb5\x1cR\xedS\x8b\xee\xf1\x1b\x04\xfc\x0c_\xad#"\xc5qO\xb3\xc5\xdd\x10\x9f\x02Hl\xdb\xde\xc2A\xec\xd0\xbb\x0c9aU??\xcdwE\xe2Ux\xa6_\xeb\xa0\x080Y\xff\x8a\xbc5L\x07\xf5!\xb3\x08\xc0/\x9ez\xfe\x0fR<_k\xe1J\xe4lN\xc4\x17/\x93\xf7\xbd\xff\x1e\x94<Ot:\xcc\'3m\x94\x10\x9b-l\xd5'
يمكن ملاحظة أن هناك 4 بايت يكتب فيها طول الحقل ، ثم الحقل نفسه ، إلخ. الحقل الأول هو اسم الخوارزمية ، والباقي يعتمد على خوارزمية معينة. في المفتاح أعلاه ، 3 حقول:
b'ssh-rsa' - b'\x01\x00\x01' - b'\x00\x9e\x88^\x0e8\xe5!Z\xf3\x98\xae\x1f\xde\xe2\xafu\xfa,\xfe\x8b\xd4\xb4\xb3s6,\xfa\xbe\x18\x08Q\x96\x12\xad\xe6\xf2\xb2\x11Wz\xc7\xa9\xb6\xe9\xc7=\xf1\x8f\x92Ay\xc2\x07\xd1\x96yV$\xf29E\x1cE\xe7c\x86\x16yb\xc3\xc1r!\x1c\x12X\xb7\x9c\xb3\xde>V\x92\x0fy\xc7\xe9\x8f\xbc\xefE- d\xfc\tv\x19\xb1\xf9\xab\xa1~\x85\x92%.c\xbar"\x12\x99~\x13\xb5\xc1\xb5\xb3\x0e\x12\xc2\x84\xc0\x0e\xba\xe1t\xcd\x0e%\xdf\x9c\xe4%<\x8a\xa0\x9bs\xa3\xf3\x9d\x86\xcbep\xaf\xa8\xf6SY\xe4\x9bL\xb5\x1cR\xedS\x8b\xee\xf1\x1b\x04\xfc\x0c_\xad#"\xc5qO\xb3\xc5\xdd\x10\x9f\x02Hl\xdb\xde\xc2A\xec\xd0\xbb\x0c9aU??\xcdwE\xe2Ux\xa6_\xeb\xa0\x080Y\xff\x8a\xbc5L\x07\xf5!\xb3\x08\xc0/\x9ez\xfe\x0fR<_k\xe1J\xe4lN\xc4\x17/\x93\xf7\xbd\xff\x1e\x94<Ot:\xcc\'3m\x94\x10\x9b-l\xd5' - N (0x101 * 8 = 2048 )
بصمة الإصبع
بصمة المفتاح المقترح التحقق منه في الاتصال الأول هي التجزئة المقابلة (في المثال SHA256) من المفتاح العام من الفقرة الأخيرة ومن /etc/ssh/ssh_host_rsa_key.pub المشفرة في base64 لتجزئة وظائف عائلة SHA أو في ست عشري لـ MD5.
نعتبر from hashlib import sha256 from base64 import b64decode, b64encode pub_key_bin = b64decode("AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh/e4q91+iz+i9S0s3M2LPq+GAhRlhKt5vKyEVd6x6m26cc98Y+SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x+mPvO9FLSBk/Al2GbH5q6F+hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd+c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti+7xGwT8DF+tIyLFcU+zxd0QnwJIbNvewkHs0LsMOWFVPz/Nd0XiVXimX+ugCDBZ/4q8NUwH9SGzCMAvnnr+D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV") hash = sha256(pub_key_bin).digest() fingerprint = b64encode(hash) print(fingerprint) > b'kd9mRkEGLo+RBBNpxKp7mInocF3/Yl/0fXRsGJ2JfYg='
+ + عز i9S0s3M2LPq + GAhRlhKt5vKyEVd6x6m26cc98Y + SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x + mPvO9FLSBk / Al2GbH5q6F + hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd + c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti + 7xGwT8DF + tIyLFcU + zxd0QnwJIbNvewkHs0LsMOWFVPz / Nd0XiVXimX + ugCDBZ / 4q8NUwH9SGzCMAvnnr + D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV") from hashlib import sha256 from base64 import b64decode, b64encode pub_key_bin = b64decode("AAAAB3NzaC1yc2EAAAADAQABAAABAQCeiF4OOOUhWvOYrh/e4q91+iz+i9S0s3M2LPq+GAhRlhKt5vKyEVd6x6m26cc98Y+SQXnCB9GWeVYk8jlFHEXnY4YWeWLDwXIhHBJYt5yz3j5Wkg95x+mPvO9FLSBk/Al2GbH5q6F+hZIlLmO6ciISmX4TtcG1sw4SwoTADrrhdM0OJd+c5CU8iqCbc6PznYbLZXCvqPZTWeSbTLUcUu1Ti+7xGwT8DF+tIyLFcU+zxd0QnwJIbNvewkHs0LsMOWFVPz/Nd0XiVXimX+ugCDBZ/4q8NUwH9SGzCMAvnnr+D1I8X2vhSuRsTsQXL5P3vf8elDxPdDrMJzNtlBCbLWzV") hash = sha256(pub_key_bin).digest() fingerprint = b64encode(hash) print(fingerprint) > b'kd9mRkEGLo+RBBNpxKp7mInocF3/Yl/0fXRsGJ2JfYg='
نرى أن التجزئة تتوافق حقًا مع بصمة الإصبع الموضحة أثناء الاتصال الأول (اقتباس في بداية المقالة) ، حتى رمز "=" في النهاية.
فيما يلي برنامج صغير للعثور على المضيفين في ملف known_hosts ، والذي ظهر أثناء التجارب.