Demand background:
I wanted to build a video-on-demand server, and finally chose the nginx+vod solution, using lua scripts to write streaming authentication, but during the environment construction process, I found that the environment of nginx++vod+lua is not easy to build, it is nginx+ The lua environment is cumbersome to build manually, but it is still possible. There is another solution that can use openresty (nginx+lua) + vod, because openresty has already included the nginx and lua environment for you, but it is not yet Contains the on-demand module vod, just add-module vod yourself
Note that the on-demand lua authentication introduced in this article only does the authentication of the m3u8 file, not the authentication of the ts file, and simply judges whether there is token authentication. As for the design of the token, you need to configure it yourself.
This article mainly introduces the construction of the environment, the analysis of the authentication process, focusing on the process, and finally the installation script and the entire configuration file of nginx.conf will be attached to the article
Option 1 nginx+vod+lua
Configure server DNS:
echo "nameserver 114.114.114.114" >> /etc/resolv.conf
Install web tools
yum install wget ntpdate git -y
Install compilation tools and dependent libraries
yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel -y
Synchronize server time
ntpdate ntp.aliyun.com
timedatectl set-timezone Asia/Shanghai
Create the installation directory of the on-demand server
I installed it in the /usr/cloudland/nginx directory
mkdir -p /usr/cloudland/nginx
export NGINX_INSTALL_PATH=/usr/cloudland/nginx
Download configuration install lua interpreter LuaJIT
wget -c http://luajit.org/download/LuaJIT-2.0.4.tar.gz
tar xzvf LuaJIT-2.0.4.tar.gz
cd LuaJIT-2.0.4
make install PREFIX=$NGINX_INSTALL_PATH/luajit
export LUAJIT_LIB=$NGINX_INSTALL_PATH/luajit/lib
export LUAJIT_INC=$NGINX_INSTALL_PATH/luajit/include/luajit-2.0
cd -
Note the above two export commands to configure the environment variables of the lua interpreter
Download nginx NDK (ngx_devel_kit) extension module
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
tar -xzvf v0.3.0.tar.gz
Download lua-nginx-module
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz
tar -xzvf v0.10.9rc7.tar.gz
Download and install the lua-resty-http module (lua library, some libraries that implement http functions)
wget https://github.com/ledgetech/lua-resty-http/archive/refs/tags/v0.16.1.tar.gz
tar -zxvf v0.16.1.tar.gz
cp -r lua-resty-http-0.16.1/lib/resty/ $NGINX_INSTALL_PATH/luajit/lib/lua/5.1/
cp -r lua-resty-http-0.16.1/lib/resty/ $NGINX_INSTALL_PATH/luajit/share/lua/5.1/
Note that NGINX_INSTALL_PATH can be replaced with your own nginx installation path. The above two cp commands are to solve the problem that resty-http cannot find
Download and install the lua-cjson module (lua library, providing json-related functions for lua)
wget https://github.com/openresty/lua-cjson/archive/refs/tags/2.1.0.9.tar.gz
tar -zxvf 2.1.0.9.tar.gz
cd lua-cjson-2.1.0.9
make LUA_VERSION=5.1 PREFIX=$NGINX_INSTALL_PATH/luajit/ LUA_INCLUDE_DIR=$NGINX_INSTALL_PATH/luajit/include/luajit-2.0/
make LUA_VERSION=5.1 PREFIX=$NGINX_INSTALL_PATH/luajit/ LUA_INCLUDE_DIR=$NGINX_INSTALL_PATH/luajit/include/luajit-2.0/ install
cd -
Pay attention to the make parameters above, the specified installation path and header files, to solve the problem that lua-cjson related libraries cannot be found
Download the nginx-vod module
This module is to realize the on-demand function for nginx
wget https://github.com/kaltura/nginx-vod-module/archive/refs/tags/1.28.tar.gz
tar -zxvf 1.28.tar.gz
Download configuration and install nginx
wget https://nginx.org/download/nginx-1.20.1.tar.gz
tar -xzvf nginx-1.20.1.tar.gz
cd nginx-1.20.1
./configure --prefix=/usr/cloudland/nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --add-module=../lua-nginx-module-0.10.9rc7 --add-module=../ngx_devel_kit-0.3.0 --add-module=../nginx-vod-module-1.28/
make
make install
Load the luajia related library
echo "$NGINX_INSTALL_PATH/luajit/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
ldconfig
Modify the nginx configuration file nginx.conf
There are two modifications
Amendment 1:
init_by_lua_block {
cjson = require "cjson";
http = require "resty.http";
}
Add location:
Modification 2:
location /vod {
rewrite_by_lua_block {
-- local cjson = require "cjson"
-- local http = require "resty.http"
local httpc = http.new()
local ngx = ngx
local headers = ngx.req.get_headers()
local extension = ngx.var.request_uri:match(".+%.(%w+)$")
local token = headers["token"]
local request_method = ngx.var.request_method
local args = nil
if "GET" == request_method then
args = ngx.req.get_uri_args()
elseif "POST" == request_method then
ngx.req.read_body()
args = ngx.req.get_post_args()
end
if extension == 'm3u8' then
token = args["token"];
if not token then
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say("Nil token,Not Privileged To Play")
-- ngx.say(ngx.var.request_uri);
-- ngx.say(extension);
ngx.exit(200)
end
-- 要实现token鉴权的服务,header和参数已经实现,根据实际需要选择
-- 可以将URL发送给一个golang服务,用golang服务来做具体鉴权
local url = "http://172.20.0.95:11985/api/rest/v1/vod/check";
local res, err = httpc:request_uri(url, {method="GET", headers={["token"]=token}})
if not res then
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
ngx.say(cjson.encode({message = "Error getting response",status = ngx.HTTP_INTERNAL_SERVER_ERROR }));
ngx.exit(200)
end
if res.body == '0' then
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
ngx.say("Valid token,Not Privileged To Play.");
ngx.exit(200)
end
end
}
vod hls; # 协议使用hls模式
vod_mode local; # 访问模式指定为local模式
vod_align_segments_to_key_frames on; # 每个切片以关键帧开头
vod_manifest_segment_durations_mode accurate; # 精确显示每个切片的长度
root /media;
#alias /media; # 视频文件路径
#proxy_pass http://172.0.0.74:80/lua;
}
Add location:
Configuration of the entire nginx.conf file
#user nobody;
worker_processes 1;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
init_by_lua_block {
cjson = require "cjson";
http = require "resty.http";
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /lua {
default_type 'text/plain';
content_by_lua 'ngx.say("hello, lua for vod")';
}
location /vod {
rewrite_by_lua_block {
-- local cjson = require "cjson"
-- local http = require "resty.http"
local httpc = http.new()
local ngx = ngx
local headers = ngx.req.get_headers()
local extension = ngx.var.request_uri:match(".+%.(%w+)$")
local token = headers["token"]
local request_method = ngx.var.request_method
local args = nil
if "GET" == request_method then
args = ngx.req.get_uri_args()
elseif "POST" == request_method then
ngx.req.read_body()
args = ngx.req.get_post_args()
end
if extension == 'm3u8' then
token = args["token"];
if not token then
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say("Nil token,Not Privileged To Play")
-- ngx.say(ngx.var.request_uri);
-- ngx.say(extension);
ngx.exit(200)
end
-- 要实现token鉴权的服务,header和参数已经实现,根据实际需要选择
-- 可以将URL发送给一个golang服务,用golang服务来做具体鉴权
local url = "http://172.20.0.95:11985/api/rest/v1/vod/check";
local res, err = httpc:request_uri(url, {method="GET", headers={["token"]=token}})
if not res then
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
ngx.say(cjson.encode({message = "Error getting response",status = ngx.HTTP_INTERNAL_SERVER_ERROR }));
ngx.exit(200)
end
if res.body == '0' then
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
ngx.say("Valid token,Not Privileged To Play.");
ngx.exit(200)
end
end
}
vod hls; # 协议使用hls模式
vod_mode local; # 访问模式指定为local模式
vod_align_segments_to_key_frames on; # 每个切片以关键帧开头
vod_manifest_segment_durations_mode accurate; # 精确显示每个切片的长度
root /media;
#alias /media; # 视频文件路径
#proxy_pass http://172.0.0.74:80/lua;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
Modify the above nginx.conf to /usr/cloudland/nginx.conf
start nginx
cd /usr/cloudland/nginx/
./sbin/nginx -p $PWD -c conf/nginx.conf
Result verification:
Turn off the firewall last before authenticating
Turn off the firewall:
systemctl stop firewalld
Just copy a video to the /media/vod directory
Open http://172.24.0.74/vod/720p-test.mp4/index.m3u8 with a browser
The above result without token
Use a browser to open the URL with token http://172.24.0.74/vod/720p-test.mp4/index.m3u8
Discovery will allow downloading the index.m3u8 file
Use VLC to open the URL with token and find that the video can be played
The script to build the whole environment:
#!/bin/sh
NGINX_INSTALL_PATH=/usr/cloudland/nginx
echo "nameserver 114.114.114.114" >> /etc/resolv.conf
yum install wget ntpdate git -y
yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel -y
ntpdate ntp.aliyun.com
timedatectl set-timezone Asia/Shanghai
# LuaJIT
if [ ! -f LuaJIT-2.0.4.tar.gz ]; then
wget -c http://luajit.org/download/LuaJIT-2.0.4.tar.gz
fi
tar xzvf LuaJIT-2.0.4.tar.gz
cd LuaJIT-2.0.4
make install PREFIX=$NGINX_INSTALL_PATH/luajit
export LUAJIT_LIB=$NGINX_INSTALL_PATH/luajit/lib
export LUAJIT_INC=$NGINX_INSTALL_PATH/luajit/include/luajit-2.0
cd -
#ngx_devel_kit
if [ ! -f v0.3.0.tar.gz ]; then
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
fi
tar -xzvf v0.3.0.tar.gz
#lua-nginx-module
if [ ! -f v0.10.9rc7.tar.gz ]; then
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz
fi
tar -xzvf v0.10.9rc7.tar.gz
#lua-resty-http
if [ ! -f v0.16.1.tar.gz ]; then
wget https://github.com/ledgetech/lua-resty-http/archive/refs/tags/v0.16.1.tar.gz
fi
tar -zxvf v0.16.1.tar.gz
cp -r lua-resty-http-0.16.1/lib/resty/ $NGINX_INSTALL_PATH/luajit/lib/lua/5.1/
cp -r lua-resty-http-0.16.1/lib/resty/ $NGINX_INSTALL_PATH/luajit/share/lua/5.1/
#lua-cjson
if [ ! -f 2.1.0.9.tar.gz ]; then
wget https://github.com/openresty/lua-cjson/archive/refs/tags/2.1.0.9.tar.gz
fi
tar -zxvf 2.1.0.9.tar.gz
cd lua-cjson-2.1.0.9
make LUA_VERSION=5.1 PREFIX=$NGINX_INSTALL_PATH/luajit/ LUA_INCLUDE_DIR=$NGINX_INSTALL_PATH/luajit/include/luajit-2.0/
make LUA_VERSION=5.1 PREFIX=$NGINX_INSTALL_PATH/luajit/ LUA_INCLUDE_DIR=$NGINX_INSTALL_PATH/luajit/include/luajit-2.0/ install
cd -
# vod module
if [ ! -f 1.28.tar.gz ]; then
wget https://github.com/kaltura/nginx-vod-module/archive/refs/tags/1.28.tar.gz
fi
tar -zxvf 1.28.tar.gz
# nginx
if [ ! -f nginx-1.20.1.tar.gz ]; then
wget https://nginx.org/download/nginx-1.20.1.tar.gz
fi
tar -xzvf nginx-1.20.1.tar.gz
cd nginx-1.20.1
./configure --prefix=$NGINX_INSTALL_PATH --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --add-module=../lua-nginx-module-0.10.9rc7 --add-module=../ngx_devel_kit-0.3.0 --add-module=../nginx-vod-module-1.28/
make
make install
cd -
echo "$NGINX_INSTALL_PATH/luajit/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
ldconfig
\cp ./nginx.conf $NGINX_INSTALL_PATH/conf
cd $NGINX_INSTALL_PATH
$NGINX_INSTALL_PATH/sbin/nginx -p $NGINX_INSTALL_PATH -c $NGINX_INSTALL_PATH/conf/nginx.conf