OpenVPN
ببساطة OpenVPN، ماهو إلا VPN. بكل ماتحمله الكلمة من معان وفوائد جما.
غالبا المؤسسات تشتري Cisco ASA، ولا F5 مثلا، أو غيرهم، لتقديم خدمة VPN للعملاء، او الموظفين، أو حتى الربط بين الفروع. الفوائد تتلخص في التالي:
- بإمكان الموظفين الدخول إلى موارد المؤسسة من المنزل. مثلا مشاركة الملفات والطابعات، استخدام الـintranet أو VoIP
- الربط بين الفروع. فعوضا من شراء Leased line أو MPLS للربط بين الفروع، يكفي انشاء VPN بين الفرعين عبر فضاء الإنترنت - وهكذا يكون السعر أرخص وتقريبا نفس معدل الأمان.
- كذلك للأفراد. شخصيا استخدم هذا في المنزل كذلك، حتى أدخل على ملفاتي أو أي شيء آخر من محل العمل.
- زيادة الأمان في الشبكات المحلية، سواء سلكية أو لاسلكية.
كل هذه الخواص يوفرها أيضا OpenVPN إلا أنه مجاني ومفتوح المصدر، وممكن تثبيته تقريبا على أي جهاز PC أو سيرفر. أنظمة التشغيل التي يدعمها:
- عائلة الـBSD و توزيعات Linux، سنتحدث عن واجهة الأوامر، لكن الواجهة الرسومية أيضا موجودة

- Windows مع واجهة رسومية للـclient
وإستخدامه للعلم أسهل من Cisco IPSec Client
هذا البرنامج، بإمكانه توفير الخدمة لمئات بل آلاف المستخدمين. الـScalability فيه مرنة جدا. كل ماعليك هو تنصيب خادم OpenVPN، وعندما تريد تتوسع، فقط تضع خادم جديد. الخادم الجديد سيملك _نفس_ الإعدادات لكن فقط رقم IP مختلف. High Availability & High Performance.
لماذا نضيع مالا لشراء مايمكن الحصول عليه بالمجان + مرونة أكبر؟
الفهرس
- مقدمة عن OpenVPN
- التثبيت على FreeBSD و Linux و Windows
- اعدادات الخادم - Server
- اعدادات العميل - Client
- التشغيل وتجربة أول اتصال
مقدمة عن OpenVPN
OpenVPN يعتبر SSL VPN، ووجه اختلافه أنه ليس بداخل الـkernel كما هو الحال مع IPSec. لذا لا داعي لـkernel recompile على سبيل المثال. وكذلك البرنامج ممكن نسميه end-to-end، فلا توجد مخافة incompatibility كما هو الحال مع IPSec. صحيح أن IPSec معيار عالمي، إلا أن التطبيقات بواسطة عدة مصنعين تتكون أحيانا غير متوافقة.
لذا برنامج OpenVPN من أسهل أنواع الـVPN. لكن عدم وجوده داخل الـKernel سيؤدي إلى بعض البطئ. هذا البطئ غير ملحوظ في معظم الأحيان، وخاصة مع الـscalability العالية ممكن استخدام عدة سيرفرات. ناهيك أن هناك مزودات vpn على فضاء الإنترنت تستخدم OpenVPN، هذا دليل على الـscalability.
آلية OpenVPN من منظور الشبكة
طريقة عمل الـOpenVPN بسيطة. فهو يتنسط على منفذ TCP أو UDP (انت تختار)، وجميع البيانات المستقبلة والمرسة بين الخادم والعميل يتم تمريرها داخل هذا المنفذ. يعني TCP/UDP tunnel.
بالإعدادات الإفتراضية يكون UDP 1194، وهذا الرقم مخصص للبرنامج بواسطة IANA للـOpenVPN. فعندما يشبك العميل مع الـVPN سيقوم بإرسال كل شيء داخل UDP 1194. وإذا تشغل wireshark ستجد أن جميع الداخل والخارج هو UDP1194، وطبعا كل مابداخله مشفر بإحكام.
مثال تطبيقي، عندما يقوم العميل، الموصول من خلال OpenVPN، إرسال طلب مشاهدة موقع جوجل، يعني HTTP GET Request to Google.com سيكون شكل الـpacket كالتالي (الأحمر مشفر):
IP_Header(SrcIP:ClientRealIP, DstIP:OpenVpnServerRealIP)
UDP_Header(SrcPort:Random, DstPort:1194)
IP_Header(SrcIP:OpenVPNVirtualIP, DstIP:Google.comIP)
TCP_Header(SrcPort:Random, DstPort:80)
HTTP_Header(GET /HTTP/1.1, Host:google.com..etc)
ممكن تختار اي منفذ TCP أو UDP. الـUDP جيد اذا كنت تنقل بيانات صوت كالـRTP - VoIP مثلا. والـTCP جيد اذا كنت تريده لتبادل ملفات. هذا بحكم تجربة عملية. ليس هذا فحسب، بل ايضا يعتمد على معدل الـdrop rate بين العميل وخادم OpenVPN. إذا كان الـdrop rate او معدل سقوط الـpackets قليل فممكن تذهب مع UDP للجميع الحالات، فهو أخف ولا يحتاج handshake.
آلية OpenVPN من منظور الخادم
داخل الخادم، الـopenvpn process يتنسط على udp1194 بالإعدادات الإفتراضية، أو ممكن تخليه tcp اذا تريد. في البداية لا يقبل الخادم أي بكت، إلا وفقط بعدما تتم عملية الـauthentication. هناك عدة طرق authentication والبرنامج مرن جدا. في هذا الدرس سأتحدث بإذن الله عن أبسطها من منظور الشرح (حتى الطرق الأخرى سهلة التطبيق).
بعدما تتم عملية الـauthentication ويتم تحديد مفاتيح التشفير وفكها، يقوم الخادم بإستقبال البكتس وتمريرها كما يجب بناء على الـrouting table. السؤال الذي يطرح نفسه. أين تتم عملية التشفير وفكه؟
آلية OpenVPN من منظور العميل
العميل لا يقوم بتشفير كل مايدخل ويخرج من المنفذ الفيزيائي، مثلا لنلق ethernet. الذي يحدث أنه سيفتح عنده tunnel interface كذلك. وجميع مايدخل ويخرج منه سيتعرض لعملية الـتشفير وفك التشفير بواسطة البرنامج وبناء على كلمات السر التي تم الاتفاق عليها.
ولهذا السبب، لو تقوم بتشغيل wireshark وتجعله يتجسس على الـtunnel interface ستشاهد كل شيء plain text لماذا؟ لأن البرنامج يقوم بفكر تشفيره عندما يستقبل قبل أن يمرره على نظام التشغيل، وكذلك يقوم بتشفيره بعدما يستقبل من نظام التشغيل وقبل ارساله إلى الـtunnel interfaces.
ولنفس السبب أيضا، لو تقوم بتشغيل wireshark وتجعله يتجسس على الـمنفذ الفيزيائي، مثلا ethernet network card، ستجد أن البيانات مشفرة وماهي إلا udp1194. والسبب أنه لا يحدث تشفير وفك تشفير في هذه المرحلة، فهنا تنظر للبكت مثلما ينظر إليه أي شخص آخر. جميع عمليات تشفير وفك تشفير تتم على الـtunnel interface.
التثبيت بمختلف الطرق
الغرنيق FreeBSD
cd /usr/ports/security/openvpn
make
make install
rehash
توزيعات Linux
Redhat/Fedora/Suse أو ماشابه
rpm -i path-to-installation-rpm-package.rpm
debian/ubuntu/linuxmint او ماشابه
sudo apt-get install openvpn
Gentoo (اقرب لينكس للصواب حسب رأيي)
emerge openvpn
Windows
http://openvpn.se/download.html نزله من هنا ثم next next حتى ينجلي.
التثبيت بالطريقة اليدوية
http://openvpn.net/index.php/open-source/downloads.html
حمل الـtar ball من هنا. ثم:
tar -xzf path-to-my-lovely-tar-ball.tar.gz
cd path-to-extracted-tar-ball-directlry/
./configure
make
make install
لكن قبل هذا تأكد ان لديك نسخة مثبتة من:
- openssl
- lzo
- pam
اعدادات الخادم - Server
مقدمة عن X.509 Certificate
أولا وقبل ذي بدء، يجب علينا انشاء Certificate Authority. طبعا عندما نسمع Authority نتخيل شيء ضخم منل جونقار ولا غرانديزر
بينما في الواقع هو عبارة عن ملفين فقط. public key, private key - قضي الأمر.
الذي يحدث كالتالي:
- certificate authority أو ca يعتبر بمثابة الجد الأكبر الذي يسمع كلامه الجميع ويثق به
- الـCA هذا، عبارة عن private key و public key: الـpublic مشهور عند الكل، والـprivate سري لا يعلمه أحد إلا صاحب الخادم ورب الأرباب سبحانه، جل عما يشبهه الأنام.
- خادم الـopenvpn، يحتاج شهادة SSL أو X.509، لذا عليه إرسال طلب وهذا اسمه CSR - Certificate SIgn Request
- الـCA - الجد الأكبر - يستقبل الطلب الـCSR ويقوم بختمه بالـprivate key الخاص به
- الملف الناتج، يكون اسمه certificate for vpm server.
- عندما يقوم العميل بالشبك مع خادم الـopenvpn، يقوم الخادم بإعطائه ذلك الـcertificate. وحتى يقوم العميل بالتأكد أن هذه الشهادة موقعة 100% بواسطة الجد الأكبر الـCA يجب على العميل أن يملك نسخة public key للـجد الأكبر الـCA، وإذا قام بفك تشفير شهادة الـopenvpn server بواسطة الـCA Public key فهذا دليل _قاطع_ أنها كانت موقعة بواسطة الـprivate key للـجد الأكبر.
- يعني ببساطة هناك قانون مع الـRSA (المعادلة المستخدمة في التشفير وفك التشفير بواسطة public/private keys) تنص على أن المفتاحين قابلين للتبادل: يعني ماتم تشفيره بالأول يتم فكه بالثاني، والعكس صحيح. ولهذا السبب اذا قام العميل بفك التشفير بالـpublic key معناه مشفر بالـprivate.
إنشاء الـX.509 Certificate + Private Key للـ Certificate Authority
أين الـpublic key؟ هو داخل شهادة الـX.509.
بما أننا على بيئة يونكس، سواء freebsd/linux، بإمكاننا انتاج هذه الشهادة بواسطة أداة openssl الغنية عن التعريف. لكن من باب التسهيل ولتجنب اخطاء ثغرات الأمان، openvpn يأتي مع مجموعة اسكربتات تقوم بالمطلوب اسمها easy-rsa. تجدها في مجلد معين. مثلا مع الغرنيق Freebsd ومع طريقة التنصيب الآلية يكون في هذا المسار:
cd /usr/local/share/doc/openvpn/easy-rsa
ثم طبق الأوامر التالية حتى تصنع certificate and private key للـCA
./clean-all
. ./vars
./build-ca
السطر الثاني حتى يقوم بتعيين قيم في متغيرات. هذه المتغيرات حتى تعلم الscript التالية عن مسارات الملفات والإعدادات المطلوبة.
السطر الثالث حتى تنشئ certificate/private key للـca. كل ماعليك هو اتباع الخطوات فالإسكربت interactive و يشرح نفسه بنفسه.
الآن لو تنظر إلى مجلد keys ستجد أنه اصبح يحتوي على private key + الـX.509 certificate للـCA.
انشاء الـ private key + X.509 Certificate للـOpenVPN Server
./build-key-server server
سيسألك أسئلة سهلة مرفقة بشرح. يعني مثل next-next بالوندوز لكن كتابي. وبالتختام سيقوم بصنع Private Key + CSR مصاحب له. وثم يختم الـCSR بواسطة الـCA التي أنشأناها مسبقا. وبعدما يختمه لك ستحصل على شهادة X.509 خاصة للخادم. طبعا ممكن تمسح ملف الـCSR لاحقا إذا شئت لا مشكلة انتهى الغرض منه. المهم الآن لديك private key + certificate
اعداد Diffie-Hellman
حسب معيار rfc5246 فـTLS1.2 يسمح لك بإختيار Cipher suites ومن ضمنها آلية اختيار مفاتيح التشفير والتوثيق من خلال عدة آليات كما هو مذكور في كما في appendix A.5. صحيح أن آلية RSA تستطيع القيام بتكوين المفاتيح، إلا أنه ممكن أيضا تترك هذه الوظيفة لـDH والذي يفعله OpenVPN. يعني RSA فقط للـauthentication و DH لتكوين مفاتيح MAC send/receive encrypt/decrypt. فحتى يعمل Diffie-Hellman بسرعة أكبر، نتجنب انتاج prime-number جديد في كل مرة، فننتجه مرة واحدة ونخزنه في ملف. وهذا بواسطة:
./build-dh
من ناحية الأمان، لا يوجد أي تأثير اطلاقا، لأنه في كلا الحالتين فإن الـPrime Number هذا سيتم تبادله بطريقة علنية. وهذا حسب الـalgorithm الخاص بـDH. حيث أن القيم التي ممكن تبادلها علنيا ولا تؤثر في الأمان هي: prime number (p) و group/base (g) والناتج من الـmod. الرقم السري الوحيد هو الـexponent أو الأس.

فخلاصة الكلام، كما ترى، لاخوف إطلاقا من استخدام نفس الـprime-number، فالقضية علنية أساسا في الحالتين.
استخدام الملفات السابقة
الآن، بناء على ماسبق، أنشأنا هذه الملفات السابقة:
- ca.crt
- ca.key
- server.crt
- server.key
- dh-1024.pem
الملفات الزرقاء، يجب أن تنسخها على الخادم والعميل يدويا.
الملفات البرتقالية، يجب أن تكون قابلة للإستخدام بواسطة الخادم OpenVPN
الملف الأحمر، يجب أن تجعله سريا، حتى تمنعه من openvpn، أفضل شيء ضعه في usb disk وضعه في صندوق ثم ابلع الصندوق حتى لا يأخذه أحد :).
هذه الملفات ستكون موجودة في المسار:
/usr/local/share/doc/openvpn/easy-rsa/keys
/usr/local/etc/openvpn/keys
وثم قم بخلق ملف جديد، اسمه:
nano my_servers_configuration.conf
port 1149
proto tcp
dev tun
ca /usr/local/etc/openvpn/keys/ca.crt
cert /user/local/etc/openvpn/keys/server.crt
key /usr/local/etc/openvpn/keys/server.key
dh /usr/local/etc/openvpn/keys/dh-1024.pem
server 10.2.0.0. 255.255.255.0
push "redirect-gateway"
push "dhcp-option DNS 10.1.0.1"
keepalklive 10 120
comp-lzo
auth-user-pass-verify /usr/local/etc/openvpn/auth.pl via-file
client-cert-not-required
username-as-common-name
الأوامر تشرح نفسها بنفسها. ففي البداية نحدد أن الخادم يتنسط على منفذ 1194 tcp و dev tun يعني أن هذا الـvpn سيكون routing وليس bridging. لمعظم المستخدمين اختر tun وانت مغمض العينين. للبعض الآخر ربما يريد bridging حتى يجمع الـbroadcast domains للبروتوكولات القديمة الغير مبنية على IP التي لاتدعم routing.
ثم نحدد الملفات المتعلقة بالتشفير وفك التشفير. بالتحديد ملفات الـTLS/SSL
ثم مدى الـIPs التي يتم توزيعها للعملاء. فالخادم سيوزع من 10.2.0.1 إلى 10.2.0.254. والأمر push "redirect-gateway" سيجعل الخادم يرسل طلب إلى العميل بأن يقوم بتغير الـrouting table عند العميل ويجعل الـdefault gateway مشيرا إلى رقم خادم OpenVPN الإفتراضي والذي أيضا سيكون في المدى نفسه.
push "dhcp-option DNS 10.1.0.1" حتى يحول خادم الـDHCP عند العميل إلى خادم آخر. هكذا ستتمكن من resolve local domain names أيضا.
keepalklive 10 120 يعني ارسل رسالة للتأكد من صحة العميل كل 10 ثواني، وإذا لم تسمع رد عقب 120 ثانية فهذا معناه العميل ميت وتعامل معه وكانه disconnected.
comp-lzo هذا حتى تقوم بضغط البيانات المستقبلة والمرسلة لزيادة الـthroughput. ميزته أنه سريع.
client-cert-not-required حتى يعلم الخادم أن العميل ليس لديه شهادة. اذا لم تضع هذا سيظن الخادم أنك تريد العميل يعطيك شهادة + كلمة سر واسم مرور. فمن باب التسهيل وضعت هذا حتى يكتفي الخادم بتوثيق اسم المستخدم وكلمة السر.
username-as-common-name هذا حتى يقوم الخادم بإستخدام اسم المستخدم كإسم موحد للمستخدم. لأنك إذا لم تفعل هذان سيتوقع الخادم أن يكون الإسم الموحد مستلخص من الـCN من الـX.509 التابعة للعميل (والتي نحن لا نستخدمها اساسا في مثالنا هذا). وهذا الغرض منه ليس للتعريف بالهوية، إنما للإستخدام الداخلي. هذا مفيد مستقبلا إذا أردت استخدام learn-address /path/to/script لكن هذه خاصية أخرى رائعة خارجة عن الموضوع (ربما لاحقا إن شاء الله)
auth-user-pass-verify سيقوم بتمرير اسم المستخدم والكلمة السرية إلى إسكربت خارجي. هذا الإسكربت كتبته بنفسي بلغة بيرل كنموذج حتى أخبركم مدى السهولة والمرونة. وطبعا بكل سهولة ممكن تجعله Integrated مع حسابات Active Directory بواسطة بروتوكول LDAP، الإحتمالات غير متناهية. كل مايقوم به return 0 اذا صحيح، أو return 1 إذا خطأ.
هذا المثال، قمت ببرمجة اسكربت صغير، اسمه auth.pl وهذا يستخدم ملفى text بسيط كـbackend للـauthentication. ملف الـtxt يحتوي على حسابات مستخدمين بصيغة uname:pword حيث أن كل سطر يحتوي على اسم مستخدم، وثم نقطتين فوق بعض، وثم الكلمة السرية. اسم المستخدم الثاني يكون نفس الشيء على السطر الثاني، وهكذا..الخ. هذا هو الإسكربت الذي يستخدمه OpenVPN بواسطة الأمر auth-user-pass-verify. الauth.pl يقوم بـreturn code 0 في حالجة النجاح، أو 1 في حالة فشل التعريف.
#!/usr/bin/perl
use warnings;
use strict;
open (FH, "<$ARGV[0]") or die "unable to open!\n";
my $uname=<FH>;
my $pword=<FH>;
chomp $uname;
chomp $pword;
close (FH);
open (FH, "/usr/local/etc/open/accounts.txt") or die "unable to open account file\n";
my @accounts=<FH>;
close (FH);
foreach (@accounts){
chomp $_;
if ($_ =~ m/^$uname\:$pword$/i){
exit 0;
}
}
exit 1;
لاحظوا فالقضية مرنة _جدا_ وأنت حر تبرمج ماتريد، بأي لغة تريد، طالما أنك تقوم بالجواب بـreturn 0 أو 1 تباعا. هذا الإسكربت كتبته بغرض التعليم وليس بغرض الـbest performance. كما تلاحظ لا يوجد indexing، إذا تريد طريقة أسرع ممكن تستخدم BerkeleyDB مثلا (تعتبر embeded db ويستخدمها العديد من LDAP implementations حتى المغلقة).
اعدادات العميل
كل ما عليك هو، أخذ نسخة من ca.cert ووضعه في مجلد openvpn حيث توجد الإعدادات. والإعدادات ماهي إلا ملف واحد، وهو بالتحديد:
client # نخبره أنه عميل، وليس خادم
dev tun # مطابق للإعداد في الخادم، سبق الشرح
proto tcp # مطابق للإعداد بالخادم، سبق الشرح
remote vpn.domainname.org 1194 # خادم الفيبي إن الذي سبقنا شرحه بالأعلى
ca /path/to/ca.cert # المسارر إلى شهادة السيرتيفيكيت أوثوريتي
auth-user-pass # مهم جدا، حتى يسأل المستخدم بكلمة سر
comp-lzo # حتى يضغط البيانات.
اعداد واستخدام العميل على توزيعات لينكس و أنظمةBSD
نفس الإعدادات بالأعلى. وحتى تشغله تكتب الأمر
sudo openvpn --config configfile.cfg
مع freebsd لا يوجد sudo لذا تقوم بـsu.
سيسألك عن اسم المستخدم والكلمة السرية. وفقط.
مبروك عليك OpenVPN مع simplified authentication :)
اعداد واستخدام العميل على وندوز
نفس الإعدادات بالأعلى. تنزل العميل بالواجهة الرسومية من موقع openvpn.se
ضع الإعدادات في مساره + شهادة الـCA في هذا المسار:
C:\Program files\OpenVPN\config
بعدها اضغط كلك ماوس يمين على ايقونة openvpn واختر connect.
سيسألك عن اسم المستخدم والكلمة السرية. وفقط.
مبروك عليك OpenVPN مع simplified authentication :)


