راه اندازی سرویس VOD با کمک Nginx با قابلیت ایمن سازی لینک ها

توی این پست قراره راجع به چگونگی پیاده سازی یک سرویس vod (اگه نمی دونین VOD چیه این لینک رو مشاهده کنین) به کمک Nginx و ماژول های اون بپردازیم.ممکنه شما هم تا حالا به این فکر کرده باشین که یه سرویسی درست کنین که بتونین باهاش یه یسری فیلم رو به بقیه نشون بدین. یعنی هم آدم ها بتونن بر اساس کیفیت اینترنتی که دارن، فیلم مورد نظر را با کیفیت متناظر ببین که دچار وقفه و لگ بین فیلم دیدنشون نشن (به این قابلیت Adaptive Bitrate گفته میشه که برای دونستن بیش تر راجع به اون میتونین این لینک رو مشاهده کنین) و هم با کمترین مقدار منابع سخت افزاری تعداد خوبی کاربر بتونن از این سرویس استفاده کنن. از طرفی لینک هایی که در اختیار کاربران قرار میگیره باید به صورتی باشه که فقط همون کاربر و سایر کاربر های مورد نظر بتونن اون فیلم رو ببین و هرکی با دونستن آدرس سایت ما و مکان فیلم مورد نظر روی سرور ما نتونه اون رو دانلود کنه.همین طور باید به صورتی باشه که کاربر ها به راحتی نتونن فیلم رو دانلود کنند و فیلم به صورت تیکه های کوچک به صورت پیوسته برای کاربر فرستاده بشه و اون بتونه فیلم رو ببینه (این کار با استفاده از پروتکل HLS انجام میشود. اگر دوست دارین بیشتر راجع به این پروتکل و اینکه چیه بدونین به این لینک مراجه کنین).همچنین اگه کاربر توی تایم معینی که ما مشخص می کنیم اون فیلم رو ندید، دیگه اون لینک معتبر نباشه و مجبور باشه از لینک جدیدی استفاده کنه.اگه شما هم دنبال آموزشی هستید که با استفاده از Nginx یک سرور Adaptive Bitrate VoD بسازید، جای درستی اومدین. در این آموزش، نصب Nginx را به صورت build کردن از سورس انجام میدیم و سپس ماژول Kaltura Nginx VoD را (که برای فعال کردن پروتکل HLS که از قابلیت Adaptive Bitrate پشتیبانی می‌کند، استفاده میکنیم) به nginx اضافه می کنیم.در آخر هم به کمک nginx secure token module و nginx secure link module لینک های خود را ایمن سازی می کنیم.ما علاوه بر nginx به ماژول های زیر هم نیاز داریم:ماژول vod Kaltura ماژول اصلی است که برای ایجاد ویدئو های mp4 repackaging به صورت on-the-fly، استفاده می شود.ماژول اعتبار سنجی secure link برای تأیید اعتبار URL ویدیو (برای احراز هویت)ماژول Secure token برای تولید توکن url و انتقال آرگومان های md5 و expires به m3u8 های بعدی و فایل های ts و key (به اصطلاح برای propagate کردن رمز نگاری url ها)گام اول - ساخت سرورشما به یک سرور اوبونتو نیاز دارید. من این سرور را با ubuntu 20.04 راه اندازی کردم، اما شما می تونید این سرور را با اوبونتو 18.04 بدون مشکل بسازید. همچنین با debian 10 نیز تست شده است.گام دوم - نصب واسبتگی هابرای build کردن ماژول Nginx و Kaltura VoD و secure token، ما به چند وابستگی برای نصب نیازمندیم. برای نصب آنها این دستور رو اجرا کنید:sudo apt update && sudo apt upgrade -ysudo apt install build-essential git libpcre3 libpcre3-dev libssl-dev zlib1g-dev ffmpeg libxml2-dev libavcodec-dev libavformat-dev گام سوم - دانلود nginxقبل از اینکه کد منبع Nginx را دانلود کنید، می‌توانید به سایت https://nginx.org/en/download.html سر بزنین تا آخرین نسخه Nginx را در حال حاضر مشاهده کنید. پس از آن می توانید با اجرای این دستور آنها را دانلود کنید:wget http://nginx.org/download/nginx-<version>.tar.gzالان آخرین ورژن استیبل 1.22.1 هستش برای همین من ورژن nginx-1.22.1 رو دانلود میکنم:wget http://nginx.org/download/nginx-1.22.1.tar.gzفایل دانلود شده را اکسترکت کنید:tar -zxvf nginx-1.22.1.tar.gzحال مشاهده می کنیم فولدری با نام nginx-1-22-1 ایجاد شده است گام چهارم - دانلود ماژول های nginx-vod-module و nginx-secure-token-module و نصب آن هاما به ماژول Nginx vod برای ساخت این سرور VoD نیاز داریم، می‌توانید Repository Github آن را در این آدرس ببینید: https://github.com/kaltura/nginx-vod-module . اکنون آخرین نسخه 1.31 است. این دستور را اجرا کنید تا آخرین نسخه ماژول را دانلود کنید:wget https://github.com/kaltura/nginx-vod-module/archive/refs/tags/1.31.tar.gzهمچنین به ماژول nginx secure token نیز نیاز داریم که می توانید آخرین نسخه آن را نیز در این آدرس ببینید: https://github.com/kaltura/nginx-secure-token-module . اکنون آخرین نسخه 1.5 است. این دستور را اجرا کنید تا آخرین نسخه ماژول را دانلود کنید:wget https://github.com/kaltura/nginx-secure-token-module/archive/refs/tags/1.5.tar.gzحال به ازای هر ماژول یک پوشه دیگر ایجاد کرده و محتویات آن ماژول را انجام ذخیره کنیم. برای این کار با استفاده از دستورات زیر پوشه های مربوطه را ایجاد میکنم:mkdir nginx-vod-module mkdir nginx-secure-token-moduleحال فایل های دانلود شده را اکسترکت می کنیم :tar -C ./nginx-vod-module --strip 1 -zxf 1.31.tar.gztar -C ./nginx-secure-token-module --strip 1 -zxf 1.5.tar.gzحال مشاهده می کنیم محتویات هر ماژول در پوشه مربوط به خودش ذخیره شده است.گام پنجم - نصب nginx و ماژول هایش از طریق build کردن source codeبه پوشه nginx-1.22.1 بروید:cd nginx-1.22.1پس از آن، nginx را پیکربندی می کنیم و گزینه های مورد نیاز را در تنظیمات nginx قرار می دهیم:./configure \ --prefix=/etc/nginx \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/run/nginx.pid \ --sbin-path=/usr/sbin/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_stub_status_module \ --with-http_realip_module \ --with-file-aio \ --with-threads \ --with-stream \ --with-http_secure_link_module \ --with-cc-opt='-O3 -mpopcnt' \ --add-module=../nginx-vod-module \ --add-module=../nginx-secure-token-moduleپس از configure کردن، این دستورات را برای نصب nginx اجرا کنید:sudo make && sudo make installبرای اطمینان از نصب درست، می توانید نسخه Nginx را بررسی کنید:sudo nginx -Vمطمئن شوید که در خروجی دستور بالا عبارات with-http_secure_link_module-- وadd-module=../nginx-vod-module-- و add-module=../nginx-secure-token-module-- را مشاهده می کنید.دستور زیر را نیز برای پاک کردن فایل های اضافی اجرا کنید:sudo rm -rf /usr/local/nginx/html /usr/local/nginx/conf/*.defaultگام ششم - کانفیگ nginx برای سرویس VODپس از نصب nginx حال باید با اعمال در تغییرات در فایل nginx.conf ، به nginx بگوییم که چه کار می خواهیم بکنیم.کانفیگ هایی که باید انجام دهیم :باید به nginx بگوییم فایل های mp4 را از پوشه ای روی سرور (local file system) پخش کند.خروجی فرمت شده با HLS باشد.ایمن کردن لینک هاsudo vi /etc/nginx/nginx.confحال کانفیگ زیر را در فایل nginx.conf پیست و ذخیره کنید :(برای ذخیره کردن و خارج شدن از vi دکمه shift را گرفته و دو بار کلید z را فشار دهید.)user www-data; worker_processes auto; pid /run/nginx.pid; events { worker_connections 1024; } http { include mime.types; access_log /var/log/nginx/access.log upstreaminfo; error_log /var/log/nginx/error.log info; server { listen 80; server_name 11.22.33.44; root /data/; vod_mode local; vod_last_modified 'Sun, 19 Nov 2000 08:52:00 GMT'; vod_last_modified_types *; vod_metadata_cache metadata_cache 512m; vod_response_cache response_cache 128m; # gzip manifests gzip on; gzip_types application/vnd.apple.mpegurl text/xml text/vtt; # file handle caching / aio open_file_cache max=1000 inactive=5m; open_file_cache_valid 2m; open_file_cache_min_uses 1; open_file_cache_errors on; aio on; location /vod/ { alias /data/vod/ ; vod hls; add_header Access-Control-Allow-Headers '*'; add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range'; add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS'; add_header Access-Control-Allow-Origin '*'; expires 100d; } } }!! توجه کنید که کانفیگ بالا برای آموزش می باشد و برای استفاده در محیط production ملاحظات بیش تری باید در نظر گرفته شود و به کانفیگ اضافه شود. !!کانفیگ بالا یک حالت خیلی ساده و معمولی می باشد. شما باید فایل های مثلا mp4 خود را در آدرس /data/vod/ قرار بدهید. حال با فرض اینکه آیپی سرور ما ۱۱.۲۲.۳۳.۴۴ است و فایل ما به نام amin.mp4 در آدرس /data/vod/ روی سرور قرار داشته باشد، ریکوئست ما باید به صورت زیر باشد:http://<server-ip-address>/vod/<video-file>/master.m3u8http://11.22.33.44:80/vod/amin.mp4/master.m3u8گام هفتم - اضافه کردن قابلیت ایمن سازی لینک هاخب تا به این جا تونستیم که یک سرویس vod ساده پیاده سازی کنیم و فیلم های خود را روی سرور قرار دهیم و کاربران هم با ارسال ریکوئست به سرور و گرفتن فایل m3u8 آن قادر به پخش آن فیلم خواهند بود.(اگر نمی دونید m3u8 چیست و چگونه با استفاده از این فایل قادر به دیدن آنلاین یک فیلم هستیم، به این لینک مراجعه کنین)حال می خواهیم کمی این کانفیگ را از لحاظ امنیتی بهتر کنیم. اگر محتویات فایل m3u8 را مشاهده کنین می بینید که آدرس ts ها به صورت absolute اومده یعنی آیپی و پورت و path دقیق سرور هم اومده که این موضوع از لحاظ امنیتی خیلی خوب نیست. برای همین باید آدرس absolute را غیر فعال کنیم. از طرفی الان فایل های ts به صورت عادی برای کاربر ارسال می شوند و هیج گونه رمزنگاری روی آن ها انجام نشده است. برای همین بهتر است یک رمز نگاری روی آن انجام دهیم که کمی کار را برای افراد متقلب سخت کنیم. (البته این کار تاثیر زیادی در امنیت سرور ندارد و باز هم اگر کسی بخواد می تواند به محتوا دسترسی پیدا کند چون ما قبل از ارسال ts ها فایل key را برای کاربر می فرستیم که با استفاده از آن بتواند ts ها را رمز گشایی کند). همچنین اندازه segment ها را هم می توان مشخص کرد که این جا برابر ۱۰ ثانیه قرار داده ایم.این بخش را در ادامه کانفیگ nginx در لوکیشن /vod/ قرار دهید:vod_segment_duration 10000; vod_hls_absolute_iframe_urls off; vod_hls_absolute_master_urls off; vod_hls_absolute_index_urls off; vod_secret_key 'secret$uri' vod_hls_encryption_method aes-128;شما می توانید برای اطلاعات از سایر کانفیگ ها و قابلیت این ماژول به صفحه گیتهاب آن مراجعه و داکیومنت آن را مطالعه فرمایید.حال باید کاری کنیم که هر کس به راحتی به لینک فیلم ها دسترسی نداشته باشد و همچنین اگر لینکی را صادر و برای کاربر ارسال کردیم، پس از مدتی منقضی شده و کاربر دیگر نتواند با استفاده از آن لینک فیلم را مشاهده کند. برای این کار این قسمت را در ادامه کانفیگ های قبلی در لوکیشن /vod/ در فایل nginx.conf قرار دهید:secure_token md5=$arg_md5&expires=$arg_expires; secure_token_types application/vnd.apple.mpegurl; secure_token_expires_time 7d; secure_token_query_token_expires_time 1h; secure_link $arg_md5,$arg_expires; secure_link_md5 '$secure_link_expires-secret' if ($secure_link = '') { return 403; } if ($secure_link = '0') { return 410; }با استفاده از ماژول secure-link ما یک تاریخ انقضا به عنوان آرگومان به url اضافه می کنیم. همچنین hash این تاریخ را با یک secret دلخواه گرفته و آن را نیز به عنوان آرگومان دیگری به url اضافه می کنیم.سپس با استفاده از ماژول secure-token این دو آرگومان را به آن می شناسانیم و می گوییم این نوع رمز نگاری لینک ها را برای فایل هایی که تایپ آن ها application/vnd.apple.mpegurl است در نظر بگیرد و اعمال کند.در بخش آخر هم که if ها آمده اند بدین صورت است که اگر کاربر یکی یا هردو آرگومان md5 و expires را اشتباه وارد کند مقدار متغیر secure_link$ برابر "" (رشته خالی) می شود و ۴۰۳ برگشت داده می شود و اگر لینک درست باشد ولی زمان آن منقضی شده باشد مقدار متغیر برابر ۰ و ارور ۴۱۰ برگشت داده می شود.گام هشتم - تنظیم nginx به عنوان systemd به سروربرای اینکه بعد از هر بار خاموش روشن شدن سرور یا ریستارت آن nginx به صورت خودکار شروع به کار کند باید آن را به عنوان یک systemd service به سیستم بشناسانیم. برای این کار یک فایل در آدرس زیر ایجاد می کنیم:sudo vi /lib/systemd/system/nginx.serviceحال کانفیگ زیر را کپی کرده و درون فایل ریخته و در آخر آن را ذخیره کنید:[Unit] Description=Nginx After=syslog.target network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx ExecReload=/usr/sbin/nginx -s reload ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.targetحال باید systemd را ریلود کنیم:sudo systemctl daemon-reloadسرویس Nginx را فعال کنید تا هنگام ریبوت شدن سرور به طور خودکار شروع به کار کند:sudo systemctl enable nginxحال سرویس را اجرا می کنیم:sudo systemctl start nginxاگر دچار مشکل شدید و ارور داد احتمالا سرویس دیگری روی پورت ۸۰ در حال اجراست. پس از اطمینان از خالی بودن پورت دوباره امتحان کنید.گام نهم - تستحال برای آنکه یک درخواستی به سرور بزنیم و ببینیم کار می کند یا نه درخواست زیر برای فیلم amin.mp4 را می زنیم. اگر 200 Ok داد یعنی درست است :curl -ILk 'http://11.22.33.44/vod/amin.mp4/master.m3u8?md5=48V4psfq_DxQ8Oag-bT1AQ&expires=1673450940'برای بدست آوردن مقدار expires مورد نظر دستور زیر را اجرا کنید (تاریخ منقضی شدن را وارد کنید):date -d '2023-01-25 18:42' +%sخروجی چیزی شبیه 1673449920 می شود که به عنوان آرگومان expires قرار می گیرد.حال hash md5 را به صورت زیر و طبق فرمولی که در کانفیگ ست کردیم ( 'secure_link_expires-secret$') ، به دست می آوریم :echo -n '1673449920-secret' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =خروجی چیزی شبیه _6rbki0PAu-E6ZSSS3wVgA می شود که به عنوان آرگومان md5 قرار می گیرد.اکنون می توانیم URL را در VLC با رفتن به Media > Open Network و وارد کردن URL کامل آن را پخش کنیم:اگر فیلم به درستی اجرا شد یعنی همه چیز درست است و درست پیاده سازی کردید.منابع : https://en.acodeof.com/video-on-demand-nginx-vod-module/https://facsiaginsa.com/nginx/build-adaptive-bitrate-vod-server-nginxhttps://www.nginx.com/blog/securing-urls-secure-link-module-nginx-plus/اگر این مطلب براتون مفید بود ممنون میشم به اشتراک بذارید :))همچنین اگه سوالی داشتید می تونین توی کامنت ها بپرسید و اگه بلد بودم سعی می کنم کمکتون کنم ؛)