nginx rtmp module添加鉴权机制

本文详细介绍了如何为Nginx-RTMP服务器添加鉴权机制,包括实现防盗链和鉴权的具体步骤,以及如何修改源代码来调用鉴权服务。

转自:https://blog.csdn.net/liuchen1206/article/details/77839039

目前直播平台非常的火爆。当前有不少的流媒体CDN,基于rtmp,http-flv和hls协议的。

也可以自己搭建私有的流媒体服务器,目前比较常见的有:Live555,EasyDarwin,Red5,DSS,Wowza,nginx-rtmp

这里重点讲解开源的nginx-rtmp服务器。但是流媒体服务器最大的一个问题就是防盗链和鉴权问题,如何防止流媒体服务器被第三方应用免费使用。

所以需要给nginx-rtmp 添加鉴权机制,大致的方案如下:

启动一个鉴权服务。提供 get_user_token 和 auth 两个api。

给每个主播或者观看直播的人员分配user id 和 token,当填写推流和拉流url需要填写鉴权参数,比如:

推流地址:

格式:推流名称?用户ID&用户Token

拉流地址:

rtmp://192.168.5.238:1982/mytv/abc123?1&1481169468_586597

先下载nginx和nginx-rtmp-module源代码

https://www.nginx.com/

https://github.com/arut/nginx-rtmp-module

在nginx-rtmp-module中的ngx_rtmp_cmd_module.c添加鉴权方法:

int auth(const char *auth_info)
{
    int ret = 0;
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in address;
    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr("127.0.0.1");
    address.sin_port = htons(8888);

    //设置读写操作超时时间
    struct timeval tv;
    tv.tv_sec = 3;
    tv.tv_usec = 0;

    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

    ret = connect(fd, (struct sockaddr *)&address, sizeof(address));
    if (ret != 0)
    {
        ngx_log_stderr(0, "connect to auth svr failed, fd:%d, ret:%d, errno:%d, errmsg:%s\n",
                       fd, ret, errno, strerror(errno));
        close(fd);
        return ret;
    }

    ngx_log_stderr(0, "connect to auth svr success!\n");
    char *pos = NULL;
    pos = strchr(auth_info, '&');
    if (pos == NULL)
    {
        ngx_log_stderr(0, "auth_info is invalid.\n");
        close(fd);
        return -1;
    }

    char user_id[100] = {0};
    char token[100] = {0};

    strncpy(user_id, auth_info, (unsigned int)(pos - auth_info));
    strncpy(token, pos + 1, (unsigned int)(auth_info + strlen(auth_info) - pos - 1));

    char req[1024] = {0};
    snprintf(req, 1024, "{\"head\":{\"cmd\":\"auth\", \"time\":%llu}, \"body\":{\"user_id\":%s, \"token\":\"%s\"}}\n",
             (unsigned long long)time(NULL), user_id, token);

    ret = send(fd, req, strlen(req), 0);
    if (ret > 0)
    {
        ngx_log_stderr(0, "send auth req success!\n");
    }
    else
    {
        ngx_log_stderr(0, "send auth req failed!, ret:%d\n", ret);
        close(fd);
        return -1;
    }

    char rsp[1024] = {0};
    ret = recv(fd, rsp, 1023, 0);
    if (ret > 0)
    {
        ngx_log_stderr(0, "rsp from auth svr:%s\n", rsp);
        char *pos = NULL;
        pos = strstr(rsp, "err");
        if (pos == NULL)
        {
            ngx_log_stderr(0, "rsq is invalid.\n");
            close(fd);
            return -1;
        }
        char err = *(pos + 5);
        if (err == '0')
        {
            ngx_log_stderr(0, "auth success!\n");
            close(fd);
            return 0;
        }
        else
        {
            ngx_log_stderr(0, "auth failed!\n");
            close(fd);
            return -1;
        }
    }
    else if (ret == 0)
    {
        ngx_log_stderr(0, "socket is colse!\n");
        close(fd);
        return -1;
    }
    else
    {
        ngx_log_stderr(0, "recv failed, ret:%d\n", ret);
    }
    close(fd);
    return ret;
}


将鉴权方法在nginx-rtmp-module中的ngx_rtmp_cmd_module.c的推流初始化方法(如下)

static ngx_int_t ngx_rtmp_cmd_publish_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in)

调用鉴权方法,具体代码如下:

static ngx_int_t ngx_rtmp_cmd_publish_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
                          ngx_chain_t *in)
{
    static ngx_rtmp_publish_t v;
    static ngx_rtmp_amf_elt_t in_elts[] = {
        /* transaction is always 0 */
        {NGX_RTMP_AMF_NUMBER,
         ngx_null_string,
         NULL, 0},

        {NGX_RTMP_AMF_NULL,
         ngx_null_string,
         NULL, 0},

        {NGX_RTMP_AMF_STRING,
         ngx_null_string,
         &v.name, sizeof(v.name)},

        {NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_STRING,
         ngx_null_string,
         &v.type, sizeof(v.type)},
    };

    ngx_memzero(&v, sizeof(v));
    if (ngx_rtmp_receive_amf(s, in, in_elts,
                             sizeof(in_elts) / sizeof(in_elts[0])))
    {
        return NGX_ERROR;
    }

    ngx_rtmp_cmd_fill_args(v.name, v.args);
    ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
                  "publish: name='%s' args='%s' type=%s silent=%d",
                  v.name, v.args, v.type, v.silent);

    //添加调用鉴权函数
    int ret = auth((const char *)v.args);
    if (ret != 0)
    {
        ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "auth failed!");
        return NGX_ERROR;
    }
    return ngx_rtmp_publish(s, &v);
}

在播放回调函数中也要调用鉴权方法,具体代码如下:

static ngx_int_t ngx_rtmp_cmd_play_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
                       ngx_chain_t *in)
{
    static ngx_rtmp_play_t v;
    static ngx_rtmp_amf_elt_t in_elts[] = {
        /* transaction is always 0 */
        {NGX_RTMP_AMF_NUMBER,
         ngx_null_string,
         NULL, 0},

        {NGX_RTMP_AMF_NULL,
         ngx_null_string,
         NULL, 0},

        {NGX_RTMP_AMF_STRING,
         ngx_null_string,
         &v.name, sizeof(v.name)},

        {NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_NUMBER,
         ngx_null_string,
         &v.start, 0},

        {NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_NUMBER,
         ngx_null_string,
         &v.duration, 0},

        {NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_BOOLEAN,
         ngx_null_string,
         &v.reset, 0}
    };

    ngx_memzero(&v, sizeof(v));
    if (ngx_rtmp_receive_amf(s, in, in_elts,
                             sizeof(in_elts) / sizeof(in_elts[0])))
    {
        return NGX_ERROR;
    }

    ngx_rtmp_cmd_fill_args(v.name, v.args);
    ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
                  "play: name='%s' args='%s' start=%i duration=%i "
                  "reset=%i silent=%i",
                  v.name, v.args, (ngx_int_t)v.start,
                  (ngx_int_t)v.duration, (ngx_int_t)v.reset,
                  (ngx_int_t)v.silent);

    //调用鉴权操作
    int ret = auth((const char *)v.args);
    if (ret != 0)
    {
        ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "auth failed!");
        return NGX_ERROR;
    }
    return ngx_rtmp_play(s, &v);
}

重新编译nginx源代码

#./configure --prefix=/home/xucuiping/tool/src/nginx_self/sdk  --add-module=/home/xucuiping/tool/src/nginx_self/src/nginx-rtmp-module-master   --with-debug

#make

#make install

启动nginx

#./nginx -c /home/xucuiping/tool/src/nginx_self/sdk/conf/nginx_rtmp.conf

测试

通过OBS推流和RTMP播放器测试验证。

原文地址:http://blog.csdn.net/cui918/article/details/53540397

在此表示感谢!

<think>好的,我需要帮助用户找到关于nginx-rtmp-module的使用教程,并指导他们如何搭建流媒体服务器。首先,我需要回忆一下之前提供的引用内容,确保回答中包含相关的信息。 用户提到了三个引用,其中引用[1]提到通过nginx-rtmp-module搭建流媒体服务器,实现了推流和播放功能。引用[2]是关于on_publish指令的语法,可能在配置时会用到。引用[3]则强调了该模块的强大功能和适用性。这些信息需要整合到回答中,确保用户了解模块的扩展性和配置可能性。 接下来,我应该分步骤说明安装和配置流程。首先,安装依赖项,比如在Ubuntu上安装编译所需的工具和库。然后,下载Nginxnginx-rtmp-module的源代码,进行编译安装。配置nginx.conf文件,设置RTMP模块的基本参数,如应用名称、监听端口、推流和播放的路径。完成配置后,启动Nginx服务,并进行推流和播放的测试,使用OBS推流,用VLC播放。 此外,用户可能需要进一步的配置,比如HLS支持、配置和日志记录。这里可以引用引用[2]提到的on_publish指令,说明如何设置URL。同时,引用[1]和[3]可以用来强调模块的可扩展性和适用场景。 最后,生成相关问题,覆盖安装问题、推流播放失败处理、HLS配置、方法以及性能优化,这样用户可以自行查找更多信息或深入解决问题。需要确保每个步骤清晰,代码和配置示例准确,避免语法错误,并正确引用提供的资料。</think>以下是关于nginx-rtmp-module的使用教程详解,结合了实际配置步骤和代码示例: ### 一、环境准备与安装 1. **安装依赖项**(以Ubuntu为例): ```bash sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev ``` 2. **下载源码并编译**: ```bash wget https://nginx.org/download/nginx-1.25.3.tar.gz git clone https://github.com/arut/nginx-rtmp-module.git tar -zxvf nginx-1.25.3.tar.gz cd nginx-1.25.3 ./configure --add-module=../nginx-rtmp-module make && sudo make install ``` ### 二、基础配置 在`/usr/local/nginx/conf/nginx.conf`中添加RTMP模块配置: ```nginx rtmp { server { listen 1935; chunk_size 4096; application live { live on; # 允许推流和播放 allow publish all; allow play all; } } } ``` 通过`sudo /usr/local/nginx/sbin/nginx -s reload`重启服务[^1] ### 三、推流与播放测试 1. **推流工具设置**(以OBS为例): - 服务器地址:`rtmp://你的IP/live` - 流密钥:自定义字符串(如`test`) 2. **播放端验证**: ```bash ffplay rtmp://你的IP/live/test ``` 或使用VLC打开网络串流地址 ### 四、进阶配置 1. **HLS直播支持**: ```nginx application hls { live on; hls on; hls_path /tmp/hls; hls_fragment 3s; } ``` 配合HTTP服务器配置HLS访问路径[^3] 2. **推流配置**: ```nginx on_publish http://localhost/auth; ``` 引用接口实现身份验证(需自行开发接口)[^2] ### 五、监控与日志 查看实时访问日志: ```bash tail -f /usr/local/nginx/logs/access.log ``` 监控流状态: ```nginx location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值