Featured image of post opensips auth和auth_db模块介绍

opensips auth和auth_db模块介绍

背景

这两个模块用于账号认证的,auth_db模块必须和auth模块一起,不能独立使用。

auth_db要使用数据库存储账号信息.和上一章kamailio的这个两个模块功能相同。

相对于kamailio,opensips支持RFC 8760更强的密码认证(SHA-512-256)

官方文档地址:

  1. auth
  2. auth_db

本次测试的opensips版本是:

version: opensips 3.3.10 (x86_64/linux)

auth 模块

参数解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 计算nonce的密钥,默认是随机生成的字符串
modparam("auth", "secret", "johndoessecretphrase")
# 设置nonce的过期时间,单位s,默认:300s
modparam("auth", "nonce_expire", 15)
# 为Remote-Party-ID添加前缀
modparam("auth", "rpid_prefix", "Whatever <")
# 为Remote-Party-ID添加后缀
modparam("auth", "rpid_suffix", "@1.2.3.4>")
# 设置realm自动删除的前缀,默认:""
modparam("auth", "realm_prefix", "sip.")
# avp变量存储RPID,默认:"$avp(rpid)"
modparam("auth", "rpid_avp", "$avp(caller_rpid)")
# 用户名存储在avp变量中,默认:"NULL"
modparam("auth", "username_spec", "$var(username)")
# 密码存储在avp变量中,默认:"NULL"
modparam("auth", "password_spec", "$var(password)")
# 密码是否使用HA1格式.
modparam("auth", "calculate_ha1", 1)

主要函数

www_challenge(realm[, qop[, algorithms]])

生成WWW-Authorize头部给响应,algorithms默认md5

  • realm: 通常为服务端的domain,如果为空,对应REGISTER使用$td,其他请求使用$fd

  • qop: 可以为:

    • auth
    • auth-int
    • auth,auth-int
  • algorithms: 可以为:

    • MD5
    • MD5-sess
    • SHA-256
    • SHA-256-sess
    • SHA-512-256
    • SHA-512-256-sess

proxy_challenge(realm[, qop[, algorithms]])

生成Proxy-Authorize头部给响应,参数和www_challenge一样。

consume_credentials()

删除认证信息,比如:删除Authorize头部,删除Proxy-Authorize头部. 必须在www_authorize()或者proxy_authorize()之后调用。

is_rpid_user_e164()

检查Remote-Party-ID是否是E164格式。

append_rpid_hf()

追加SIP URI到Remote-Party-ID头部字段。

append_rpid_hf(prefix, suffix)

追加前后缀到Remote-Party-ID头部字段。

pv_www_authorize(realm)

验证credentials是否正确,如果正确,标记此credentials已经验证了,如果失败,后面可以主动调用www_challenge()再次请求验证。

  • 返回值:
    • -5: 通用错误,不发送回复
    • -4: 请求没有credentials
    • -3: nonce状态
    • -2: 密码错误
    • -1: 用户名错误

pv_proxy_authorize(realm)

验证credentials是否正确,如果正确,标记此credentials已经验证了,如果失败,后面可以主动调用proxy_challenge()再次请求验证。

auth_db 模块

使用到的数据表subscriberuri

参数解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 数据库连接
modparam("auth_db", "db_url", "DBURL")
# 是否使用HA1格式的密码来认证
modparam("auth_db", "calculate_ha1", 1)
# 是否使用domain
modparam("auth_db", "use_domain", 1)
# 设置是否加载credentials到avp变量,默认:""
modparam("auth_db", "load_credentials", "$avp(13)=rpid;email_address")
# 设置是否跳过版本检查,默认:0
modparam("auth_db", "skip_version_check", 1)

主要函数

www_authorize(realm, table)

验证credentials是否正确,如果正确,标记此credentials已经验证了,如果失败,后面可以主动调用www_challenge()再次请求验证。

  • 返回值:

    • -5: 通用错误,不发送回复
    • -4: 请求没有credentials
    • -3: nonce状态
    • -2: 密码错误
    • -1: 用户名错误
  • realm: 通常为服务端的domain,如果为空,对应REGISTER使用$td,其他请求使用$fd

  • table: 数据库表名

proxy_authorize(realm, table)

验证credentials是否正确,如果正确,标记此credentials已经验证了,如果失败,后面可以主动调用proxy_challenge()再次请求验证。 入参,返回值和www_authorize一样。

db_is_to_authorized(table)

检查To头部的URI是否是授权的。

db_is_from_authorized(table)

检查From头部的URI是否是授权的。

db_does_uri_exist(uri, table)

检查 username@domain 是否存在subscriber表中

db_get_auth_id(table, uri, auth, realm)

检查uri是否存在subscriber表中.

实战

不使用数据库

配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
socket=udp:172.16.4.111:5261
...
loadmodule "auth.so"
modparam("auth", "nonce_expire", 60)
modparam("auth", "username_spec", "$var(username)")
modparam("auth", "password_spec", "$var(password)")
modparam("auth", "calculate_ha1", 1)

route {
    ...
    if (is_method("REGISTER")) {
        $var(username)="1007";
        $var(password)="1234";
        if (!pv_www_authorize("")) {
                www_challenge("", "auth,auth-int");
                exit;
        }

        # indicate that the client supports DTLS
        # so we know when he is called
        if (isflagset("SRC_WS"))
                setbflag("DST_WS");

        fix_nated_register();
        if (!save("location"))
                sl_reply_error();

        exit;
    }
    if (!lookup("location","m")) {
        t_newtran();
        t_reply(404, "Not Found");
        exit;
    }
    route(relay);
}

说明: 如果要使用SHA-512-256SHA-512-256-sess算法,openssl需要升级版本>=1.1.1, 否则会报错。

1
2
3
core:dauth_fixup_algorithms: Unsupported algorithm type: "SHA-512-256"
May 26 14:24:13 [242] ERROR:core:fix_cmd: Fixup failed for param [3]
May 26 14:24:13 [242] ERROR:core:fix_actions: Failed to fix command <www_challenge>

输出结果

  • 使用软电话注册号码1007,密码1234,注册成功: sip

可以看到在401 信令上,WWW-Authenticate头部包含qopalgorithm

  • 如果用户名或者密码错误,sip信令图: sip

  • 使用pv_proxy_authenticate()函数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
route {
    if (is_method("REGISTER")) {
        $var(username)="1007";
        $var(password)="1234";
        if (!pv_proxy_authorize("")) {
            proxy_challenge("", "auth,auth-int","SHA-256");  # Realm will be autogenerated
            exit;
        }

        # indicate that the client supports DTLS
        # so we know when he is called
        if (isflagset("SRC_WS"))
            setbflag("DST_WS");

        fix_nated_register();
        if (!save("location"))
            sl_reply_error();

        exit;
    }
}

输出的信令图: sip

可以看到在407 信令上,Proxy-Authenticate头部包含qopalgorithm

使用数据库

配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
socket=udp:172.16.4.111:5261
...
loadmodule "auth.so"
modparam("auth", "nonce_expire", 60)
modparam("auth", "username_spec", "$var(username)")
modparam("auth", "password_spec", "$var(password)")
#modparam("auth", "calculate_ha1", 1)

loadmodule "auth_db.so"
modparam("auth_db", "db_url", "DBURL")
#modparam("auth_db", "calculate_ha1", 1)

route {
    ...
    if (is_method("REGISTER")) {
        if (!www_authorize("", "subscriber")) {
                www_challenge("", "auth","SHA-256");
                exit;
        }

        # indicate that the client supports DTLS
        # so we know when he is called
        if (isflagset("SRC_WS"))
                setbflag("DST_WS");

        fix_nated_register();
        if (!save("location"))
                sl_reply_error();

        exit;
    }

}

数据表subscriber的结构为: subscriber

ha1字段的计算方式: md5(username:realm:password)

ha1_sha256字段的计算方式: sha256(username:realm:password)

ha1_sha512t256 字段的计算方式: sha512t256(username:realm:password)

添加用户:

  1. 使用opensips-cli 客户端创建用户:
1
opensips-cli -f ./opensips-cli.cfg -x user add 1007@172.16.4.111 1234
  1. 直接在数据表添加用户:
1
insert into subcriber ('username','domain','password','ha1','ha1_sha256')values('1007','172.16.4.111','1234','167f7cc6ce5f65305e413cd7d040cce3','467bd26ba1d413546561c0f3c32cd85f1c162ee84c19acb687efc6faa6c11266')

输出结果

使用md5算法,注册成功: sip

如果使用HA1算法,放开配置modparam("auth_db", "calculate_ha1", 1),目前未注册成功: sip

日志报错: log

一直报错:sha256认证失败, 但是数据库中ha1_sha256字段的值是正确的。暂时未找到问题所在。

总结

  1. opensips在不使用数据库的情况下, 用户名和密码都要设置, kamailio只设置密码。
  2. opensips支持MD5,SHA-256SHA-512-256算法, kamailio支持MD5,SHA-256算法。
本博客已稳定运行
发表了37篇文章 · 总计67.06k字
本站总访问量 次 · 您是本站第 位访问者
粤ICP备2025368587号-1| 使用 Hugo 构建
主题 StackJimmy 设计