Initial LisgloSIPS V2 implementation

This commit is contained in:
hectorzhao
2026-06-22 10:56:38 +08:00
commit 5fa1bd35e9
303 changed files with 35644 additions and 0 deletions
+836
View File
@@ -0,0 +1,836 @@
# OpenSIPS installation notes
中文说明:OpenSIPS 安装与修复备忘。
This file records the installation performed on workstation `100.93.185.30`
and the missing pieces found afterwards. Use `install-opensips-stack.sh` for a
repeatable production install.
中文说明:这个文件记录了 `100.93.185.30` 工作站上的安装过程、后来补齐的缺失模块,以及生产环境一键安装时应复用的脚本。
## Target stack
中文说明:目标软件栈。
- OS: Ubuntu 24.04 Noble
- OpenSIPS: 3.6.x from `https://apt.opensips.org`
- OpenSIPS Control Panel: 9.3.6
- RTPengine: Ubuntu `rtpengine-daemon`
- Database: MariaDB
- Web server: Apache + PHP
## Production one-shot install
中文说明:生产环境一键安装方式。
Copy `install-opensips-stack.sh` to a fresh Ubuntu 24.04 server and run:
中文说明:把 `install-opensips-stack.sh` 拷贝到一台全新的 Ubuntu 24.04 服务器上,然后执行下面命令。
```bash
sudo -E SIP_IP=YOUR_SERVER_IP DB_PASS='CHANGE_ME' bash install-opensips-stack.sh
```
Useful variables:
中文说明:下面这些环境变量可以按生产环境修改,例如服务器 IP、数据库密码、MI 端口、RTPengine 端口范围、Monit 账号等。
```bash
SIP_IP=100.93.185.30
SIP_DOMAIN=100.93.185.30
DB_NAME=opensips
DB_USER=opensips
DB_PASS=opensipsrw
CP_VERSION=9.3.6
MI_HTTP_IP=127.0.0.1
MI_HTTP_PORT=8888
RTPENGINE_NG=127.0.0.1:2223
RTPENGINE_PORT_MIN=30000
RTPENGINE_PORT_MAX=40000
MONIT_IP=127.0.0.1
MONIT_PORT=2812
MONIT_USER=admin
MONIT_PASS=monit
```
After installation:
中文说明:安装完成后,OpenSIPS-CP 管理页面和默认账号如下。
```text
OpenSIPS-CP: http://YOUR_SERVER_IP/cp/
Default user: admin
Default pass: opensips
```
Change the OpenSIPS-CP admin password before production use.
中文说明:生产环境必须修改 OpenSIPS-CP 默认管理员密码,避免后台被默认口令登录。
## Startup and boot enablement
中文说明:服务启动和开机自启。
OpenSIPS itself is a systemd service:
中文说明:OpenSIPS 本体是 systemd 服务,下面命令用于设置开机自启、重启、查看是否运行和是否启用。
```bash
sudo systemctl enable opensips
sudo systemctl restart opensips
systemctl is-active opensips
systemctl is-enabled opensips
```
Expected result:
中文说明:期望看到 `active``enabled`,表示服务正在运行并已设置开机启动。
```text
active
enabled
```
OpenSIPS-CP is the web control panel at:
中文说明:OpenSIPS-CP 是 Web 管理后台,通过 `/cp/` 访问。
```text
http://YOUR_SERVER_IP/cp/
```
It is served by Apache and uses MariaDB, so there is no separate
`opensips-cp.service` to enable. Enable and start these services instead:
中文说明:OpenSIPS-CP 不是独立服务,它依赖 Apache 提供网页、MariaDB 存配置和数据,所以要启用的是 `apache2``mariadb`
```bash
sudo systemctl enable apache2 mariadb
sudo systemctl restart mariadb
sudo systemctl restart apache2
systemctl is-active apache2 mariadb
systemctl is-enabled apache2 mariadb
```
Expected result:
```text
active
active
enabled
enabled
```
Useful verification commands:
中文说明:下面命令用于确认 SIP 端口、Web 端口、CP 页面和 MI HTTP 接口都正常。
```bash
ss -lunp | grep ':5060'
ss -ltnp | grep ':80'
curl -fsSI http://127.0.0.1/cp/
curl -fsS -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"ps"}'
```
On the current workstation, the public access URL is:
中文说明:当前这台工作站的访问地址如下。
```text
http://100.93.185.30/cp/
```
## Packages that must not be missed
中文说明:容易漏装但必须安装的软件包。
Base OpenSIPS packages:
中文说明:OpenSIPS 主程序、CLI、MySQL、认证和 TLS 相关基础包。
```bash
opensips
opensips-cli
opensips-mysql-module
opensips-auth-modules
opensips-tls-module
```
Database schema package:
中文说明:OpenSIPS 数据库建表脚本包。
```bash
opensips-mysql-dbschema
```
This one is easy to miss. Without it, `/usr/share/opensips/mysql/*.sql` is not
available and `opensipsdbctl` may not exist on OpenSIPS 3.6 installs.
中文说明:这个包很容易漏。没有它就找不到 `/usr/share/opensips/mysql/*.sql`,后续建表和导入模块表会很麻烦。
OpenSIPS-CP MI support:
中文说明:OpenSIPS-CP 通过 MI 接口控制 OpenSIPS,下面两个包提供 HTTP MI 和 JSON 支持。
```bash
opensips-http-modules
opensips-json-module
```
These provide `httpd.so`, `mi_http.so` and JSON support. Without them,
OpenSIPS-CP actions such as `Reload on Server` will fail when configured for
`json:127.0.0.1:8888/mi`.
中文说明:没有这些模块时,CP 页面里的 `Reload on Server` 会连不上 `127.0.0.1:8888/mi` 或提示 MI 命令不可用。
SIP user authentication and database registration:
中文说明:SIP 用户认证和注册落库需要的模块。
```bash
opensips-auth-modules
opensips-mysql-module
```
Enable these modules in `opensips.cfg`:
中文说明:在 `opensips.cfg` 中启用认证模块和位置服务模块,让用户可以用数据库账号注册到 OpenSIPS。
```opensips
loadmodule "auth.so"
loadmodule "auth_db.so"
modparam("auth_db", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("auth_db", "calculate_ha1", 1)
loadmodule "usrloc.so"
modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("usrloc", "working_mode_preset", "single-instance-sql-write-through")
```
Then protect REGISTER requests:
中文说明:下面这段用于保护 REGISTER 请求;没有正确账号密码的终端不能注册。
```opensips
if (is_method("REGISTER")) {
if (!www_authorize("$fd", "subscriber")) {
www_challenge("$fd", "auth");
exit;
}
if (!save("location"))
xlog("failed to register AoR $tu\n");
exit;
}
```
`calculate_ha1=1` lets OpenSIPS calculate the digest hash from the plain
`subscriber.password` column created by OpenSIPS-CP.
中文说明:`calculate_ha1=1` 表示 OpenSIPS 可以根据 `subscriber.password` 明文密码计算 SIP Digest 认证需要的 hash。
Dialog tracking for the OpenSIPS-CP Dialog page:
中文说明:Dialog 页面用于查看在线通话/会话状态,需要启用 `dialog.so`
```opensips
loadmodule "dialog.so"
modparam("dialog", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("dialog", "profiles_no_value", "inbound;outbound")
modparam("dialog", "profiles_with_value", "caller;callee")
```
Create dialog state for initial INVITEs:
中文说明:初始 INVITE 到来时创建 dialog 状态,并把主叫、被叫等信息放进 profile,便于 CP 页面查看。
```opensips
if (is_method("INVITE")) {
create_dialog();
set_dlg_profile("outbound");
set_dlg_profile("caller", "$fU");
set_dlg_profile("callee", "$rU");
do_accounting("log");
}
```
Without `dialog.so`, OpenSIPS-CP Dialog pages fail with:
中文说明:如果没加载 `dialog.so`,Dialog 页面会报下面这个 MI 方法不存在。
```text
MI command failed with code -32601 (Method not found)
```
Validation:
中文说明:验证 Dialog MI 命令是否可用。
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"dlg_list"}'
```
Dispatcher support for the OpenSIPS-CP Dispatcher page:
中文说明:Dispatcher 页面用于管理/查看后端服务器分发列表,需要启用 `dispatcher.so`
```opensips
loadmodule "dispatcher.so"
modparam("dispatcher", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("dispatcher", "persistent_state", 1)
```
Without `dispatcher.so`, OpenSIPS-CP Dispatcher pages fail with:
中文说明:如果没加载 `dispatcher.so`Dispatcher 页面会报下面这个 MI 方法不存在。
```text
MI command failed with code -32601 (Method not found)
```
Validation:
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"ds_list"}'
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"ds_reload"}'
```
Dynamic Routing support for the OpenSIPS-CP Dashboard and Dynamic Routing pages:
中文说明:Dynamic Routing 是动态路由/LCR 能力,用于管理落地网关、路由规则、网关状态,也支撑 Dashboard 的动态路由小组件。
```opensips
loadmodule "drouting.so"
modparam("drouting", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("drouting", "drd_table", "dr_gateways")
modparam("drouting", "drr_table", "dr_rules")
modparam("drouting", "drg_table", "dr_groups")
modparam("drouting", "drc_table", "dr_carriers")
```
The Dashboard `Dynamic Routing` widget calls MI commands such as
`dr_gw_status` and `dr_reload_status`. Without `drouting.so`, Dashboard may show:
中文说明:Dashboard 上的 `Dynamic Routing` 卡片会调用 `dr_gw_status` 等命令;如果没加载 `drouting.so`Dashboard 会出现 Method not found。
```text
MI command failed with code -32601 (Method not found)
```
Validation:
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"dr_gw_status"}'
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"dr_reload_status"}'
```
On a fresh system with no dynamic-routing gateways configured, `dr_gw_status`
should return an empty `Gateways` list, not `Method not found`.
中文说明:新系统没有配置网关时,返回空网关列表是正常的;错误是 `Method not found`,说明模块没加载。
RTPengine:
中文说明:RTPengine 是媒体代理,负责 RTP 媒体流转发、NAT 穿透,也可配合录音。
```bash
rtpengine-daemon
```
OpenSIPS-CP has two separate media relay pages:
中文说明:OpenSIPS-CP 里 RTPProxy 和 RTPEngine 是两个不同页面,分别对应不同 OpenSIPS 模块。
- `RTPProxy` uses the OpenSIPS `rtpproxy.so` module and MI commands such as
`rtpproxy_show`, `rtpproxy_reload`, and `rtpproxy_enable`.
- `RTPEngine` uses the OpenSIPS `rtpengine.so` module and MI commands such as
`rtpengine_show`, `rtpengine_reload`, and `rtpengine_enable`.
If either module is not loaded, its page fails with:
中文说明:对应模块没加载时,页面会报 MI 命令不存在。
```text
MI command failed with code -32601 (Method not found)
```
For this workstation, RTPengine is the actual media proxy daemon. RTPProxy is
loaded only so the OpenSIPS-CP RTPProxy page can call its MI commands; without
RTPProxy sockets configured, the page should show an empty list instead of a
Method not found error.
中文说明:当前工作站实际使用的是 RTPengine。RTPProxy 模块只是为了让 CP 的 RTPProxy 页面不报错;没有配置 RTPProxy socket 时显示空列表是正常的。
OpenSIPS module config:
中文说明:下面配置同时启用 `rtpengine.so``rtpproxy.so`,分别对应两个 CP 页面。
```opensips
loadmodule "rtpengine.so"
modparam("rtpengine", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("rtpengine", "db_table", "rtpengine")
loadmodule "rtpproxy.so"
modparam("rtpproxy", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("rtpproxy", "db_table", "rtpproxy_sockets")
```
RTPengine DB row used on the current workstation:
中文说明:当前工作站的 RTPengine 控制 socket 是 `udp:127.0.0.1:2223`,需要写入 `rtpengine` 表。
```sql
INSERT INTO rtpengine (socket, set_id)
SELECT 'udp:127.0.0.1:2223', 0
WHERE NOT EXISTS (
SELECT 1 FROM rtpengine WHERE socket='udp:127.0.0.1:2223' AND set_id=0
);
```
Validation:
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"rtpengine_show"}'
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"rtpproxy_show"}'
```
## OpenSIPS-CP SIP Trace page
中文说明:OpenSIPS-CP 的 SIP Trace 页面。
The SIP Trace page displays SIP messages captured by OpenSIPS and stored in the
`sip_trace` table. It is useful for troubleshooting registration, INVITE call
setup, routing, authentication challenges, and failed SIP responses. It lets
you filter by:
中文说明:SIP Trace 用于查看 OpenSIPS 抓到的 SIP 报文,适合排查注册失败、呼叫不通、路由错误、认证失败和 SIP 响应异常。
- `RegExp`: text or regex to search in captured SIP messages.
- `Call ID`: one SIP dialog/transaction identifier.
- `Traced User`: the trace attribute saved by the script, here `$fU`.
- `Start Date` / `End Date`: time range.
- `Group results by Call ID`: groups multiple SIP messages from the same call.
If the page shows:
中文说明:如果 SIP Trace 页面出现下面的错误,说明 `trace` MI 命令不存在。
```text
MI command failed with code -32601 (Method not found)
```
then OpenSIPS-CP called the `trace` MI command, but OpenSIPS did not load the
`tracer.so` module.
中文说明:原因是 CP 调用了 `trace` 命令,但 OpenSIPS 没加载 `tracer.so`
OpenSIPS module config:
中文说明:下面配置开启 tracer 模块,并把 trace 数据写入 MySQL 的 `sip_trace` 表。
```opensips
loadmodule "tracer.so"
modparam("tracer", "trace_on", 1)
modparam("tracer", "trace_id", "[tid]uri=mysql://opensips:opensipsrw@localhost/opensips;table=sip_trace;")
```
Main route hook used on the current workstation:
中文说明:仅启用模块还不会自动写入数据,路由脚本里需要调用 `trace()`
```opensips
route{
trace("tid", "m", "sip", "$fU");
```
The `trace` MI command only toggles tracing on/off. The `trace()` call in the
routing script is what actually writes messages to the `sip_trace` database
table.
中文说明:MI 的 `trace` 命令只是开关;真正把 SIP 消息写进数据库的是路由脚本中的 `trace()` 函数。
Validation:
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"trace"}'
mysql -D opensips -e "SELECT COUNT(*) FROM sip_trace;"
```
SIP Trace can grow quickly on a busy server. In production, keep it disabled by
default or clean old rows regularly.
中文说明:生产环境要谨慎开启 SIP Trace,因为话务量大时 `sip_trace` 表会增长很快,应定期清理或只在排障时开启。
Web/database dependencies:
中文说明:Web 前端和数据库依赖包。
```bash
mariadb-server mariadb-client
apache2 libapache2-mod-php
php php-cli php-mysql php-gd php-pear php-apcu php-curl php-xml php-mbstring
git unzip curl
```
Monit support for the OpenSIPS-CP Monit page:
中文说明:Monit 页面用于查看服务器服务和系统状态,需要安装 `monit`
```bash
monit
```
OpenSIPS-CP's Monit page is a proxy to Monit's own HTTP interface. If `monit`
is not installed or the OpenSIPS-CP box has no `monit_conn`, the page may show:
中文说明:CP 的 Monit 页面实际是代理访问 Monit 自带 HTTP 页面;如果 Monit 没装或 CP 的 box 没配置 `monit_conn`,就会报空地址。
```text
Failed to parse address ""
Error: 1
I can't connect!
```
Configure Monit to listen locally:
中文说明:Monit 只监听本机 `127.0.0.1:2812`,避免暴露到外网。
```monit
set httpd port 2812 and
use address 127.0.0.1
allow 127.0.0.1
allow admin:monit
```
Enable it:
```bash
sudo monit -t
sudo systemctl enable monit
sudo systemctl restart monit
```
Configure the OpenSIPS-CP default box:
中文说明:把 OpenSIPS-CP 默认 box 的 Monit 连接地址、账号和密码写入数据库。
```sql
UPDATE ocp_boxes_config
SET monit_conn='127.0.0.1:2812',
monit_user='admin',
monit_pass='monit',
monit_ssl=0
WHERE id=1;
```
Validation:
```bash
systemctl is-active monit
systemctl is-enabled monit
ss -ltnp | grep ':2812'
curl -fsS -u admin:monit http://127.0.0.1:2812/ | grep -m1 Monit
```
On the current workstation, Monit is installed, enabled, and bound to
`127.0.0.1:2812`. The OpenSIPS-CP default box uses `admin` / `monit`.
中文说明:当前工作站已经安装并启用 Monit,CP 使用 `admin / monit` 连接本机 Monit。生产环境请修改密码。
## OpenSIPS config added during the fix
中文说明:安装后补加到 OpenSIPS 配置里的关键修复项。
The initial installation only had `mi_fifo`. OpenSIPS-CP was configured to call:
中文说明:最初只有 `mi_fifo`,但 CP 配置的是 JSON HTTP MI,所以页面 reload 会失败。
```text
json:127.0.0.1:8888/mi
```
So `Reload on Server` failed with:
中文说明:因此 CP 页面点击 `Reload on Server` 时会连接不上 8888 端口。
```text
Failed to connect to 127.0.0.1 port 8888
```
The fix was to load HTTP MI:
中文说明:修复方法是加载 `httpd.so``mi_http.so`,让 OpenSIPS 提供本地 HTTP MI 接口。
```opensips
loadmodule "httpd.so"
modparam("httpd", "ip", "127.0.0.1")
modparam("httpd", "port", 8888)
loadmodule "mi_http.so"
modparam("mi_http", "root", "mi")
```
After that, the MI endpoint worked, but `address_reload` returned:
中文说明:HTTP MI 通了以后,`address_reload` 又报方法不存在,这是因为还没加载权限模块。
```text
Method not found
```
That command is provided by `permissions.so`, so the next fix was:
中文说明:`address_reload``permissions.so` 提供,所以需要加载 permissions 模块并配置数据库。
```opensips
loadmodule "db_mysql.so"
loadmodule "permissions.so"
modparam("permissions", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("permissions", "address_table", "address")
```
Validation command:
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"address_reload"}'
```
Expected result:
中文说明:期望返回 OK。
```json
{"jsonrpc":"2.0","result":"OK","id":1}
```
## OpenSIPS-CP Addresses page
中文说明:OpenSIPS-CP 的 Addresses 页面。
The Addresses page writes to the `address` table used by the `permissions`
module.
中文说明:Addresses 页面配置的是 IP 访问规则/白名单类规则,写入 `permissions` 模块使用的 `address` 表。
It is not where the local OpenSIPS listening IP is configured. The listening IP
belongs in:
中文说明:这里不是配置 OpenSIPS 本机监听 IP 的地方;本机监听 IP 要写在 `opensips.cfg``socket`
```text
/etc/opensips/opensips.cfg
```
Example:
```opensips
socket=udp:100.93.185.30:5060
```
Typical Address entry:
中文说明:典型地址规则示例如下。
```text
Group: 1
IP: 47.97.162.65
Mask: 32
Port: 5060
Protocol: any
Pattern:
Context Info: lisglo
```
Notes:
中文说明:字段注意事项。
- `Group` must be numeric.
- `Pattern` is an optional wildcard pattern used by `permissions` matching.
- `Context Info` is returned to the OpenSIPS script when the rule matches.
- Click `Reload on Server` after editing Addresses.
## OpenSIPS-CP Domains validation issue
中文说明:OpenSIPS-CP Domains 页面表单校验问题。
On OpenSIPS-CP 9.3.6, the Domains page may reject both IP addresses and normal
FQDNs in the `SIP Domain` field. The symptom is a red validation icon next to
the field and the `Add New Domain` button stays disabled.
中文说明:在 OpenSIPS-CP 9.3.6 中,Domains 页面可能错误拒绝 IP 和普通域名,表现为输入框旁边红色校验图标,添加按钮不可点。
This is not a SIP limitation. SIP domains may be IPs or FQDNs, and the Domains
tool itself says:
中文说明:这不是 SIP 协议限制,SIP domain 可以是 IP,也可以是 FQDN 域名。
```text
A SIP Domain to be considered local by OpenSIPS - can be an IP or a FQDN
```
The issue is in the browser-side form validation generator:
中文说明:问题在 CP 前端表单校验生成器。
```text
/var/www/html/opensips-cp/web/common/forms.php
```
The code uses `preg_quote()` when embedding validation regexes into JavaScript.
That escapes the regex into a literal string, so JavaScript's `RegExp()` no
longer receives the intended regex.
中文说明:代码用 `preg_quote()` 把正则转给 JavaScript,导致正则被转义成普通字符串,浏览器端校验失效。
Patch:
中文说明:下面补丁把 `preg_quote()` 改成更适合 JS 字符串的 `addslashes()`
```bash
sudo cp -a /var/www/html/opensips-cp/web/common/forms.php \
/var/www/html/opensips-cp/web/common/forms.php.bak.regexfix.$(date +%Y%m%d%H%M%S)
sudo python3 - <<'PY'
from pathlib import Path
p = Path('/var/www/html/opensips-cp/web/common/forms.php')
s = p.read_text()
s = s.replace("preg_quote($re, '/')", "addslashes($re)")
s = s.replace("preg_quote($value['validation_regex'], '/')", "addslashes($value['validation_regex'])")
p.write_text(s)
PY
php -l /var/www/html/opensips-cp/web/common/forms.php
```
On some OpenSIPS-CP 9.3.6 installs, the Domains page can still reject input
after the common form-generator patch because the Domains template ships its
own over-escaped field regex. If both IPs and normal FQDNs still show a red
validation icon, patch the Domains form itself:
中文说明:有些安装即使修了通用表单生成器,Domains 页面自己的字段正则仍然会过度转义,需要单独修 Domains 模板。
```bash
sudo cp -a /var/www/html/opensips-cp/web/tools/system/domains/template/domains.form.php \
/var/www/html/opensips-cp/web/tools/system/domains/template/domains.form.php.bak.domain-regex.$(date +%Y%m%d%H%M%S)
sudo python3 - <<'PY'
from pathlib import Path
p = Path('/var/www/html/opensips-cp/web/tools/system/domains/template/domains.form.php')
s = p.read_text()
lines = []
for line in s.splitlines():
if '"domain", "n", $domain_form' in line:
indent = line[:len(line) - len(line.lstrip())]
lines.append(indent + '"domain", "n", $domain_form[\'domain\'], 128, null);')
else:
lines.append(line)
p.write_text('\n'.join(lines) + '\n')
PY
php -l /var/www/html/opensips-cp/web/tools/system/domains/template/domains.form.php
sudo systemctl reload apache2 || sudo systemctl restart apache2
```
This only disables the browser-side regex for the `SIP Domain` field; the field
remains required, and the database/OpenSIPS domain module still determine what
is actually usable. After patching, hard refresh the browser with `Ctrl+F5`.
中文说明:这个修复只关闭 SIP Domain 字段的浏览器端正则,字段仍是必填;真正是否可用仍由数据库和 OpenSIPS domain 模块决定。修完后浏览器要 `Ctrl+F5` 强制刷新。
The one-shot installer already applies both equivalent patches automatically.
中文说明:一键安装脚本已经自动包含这两个补丁。
For the current workstation, `100.93.185.30` was also inserted directly into the
`domain` table to unblock user creation:
中文说明:当前工作站为了先让用户创建功能可用,已经把 `100.93.185.30` 直接写入 `domain` 表。
```sql
INSERT INTO domain (domain, attrs, accept_subdomain, last_modified)
SELECT '100.93.185.30', NULL, 0, NOW()
WHERE NOT EXISTS (SELECT 1 FROM domain WHERE domain='100.93.185.30');
```
The `domain` runtime module was enabled:
中文说明:同时启用了 OpenSIPS 的 `domain.so` 模块,并使用数据库模式。
```opensips
loadmodule "domain.so"
modparam("domain", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")
modparam("domain", "db_mode", 1)
```
Validation:
```bash
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"domain_reload"}'
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"domain_dump"}'
```
Expected `domain_dump` output includes:
中文说明:期望 `domain_dump` 输出中包含当前服务器域名/IP。
```text
100.93.185.30
```
## Security notes
中文说明:安全注意事项。
- Keep MI HTTP bound to `127.0.0.1`.
- Do not expose `0.0.0.0:8888` to the network.
- Change the OpenSIPS-CP admin password.
- Use a stronger database password in production.
- Restrict SIP source IPs using `permissions` / `address` rules.
- Open RTP port range only where needed, for example `30000-40000/udp`.
## Runtime checks
中文说明:运行状态检查命令。
```bash
systemctl is-active mariadb apache2 opensips rtpengine-daemon
ss -ltnup | grep -E '(:80|:5060|:8888|:2223|:2812)'
curl -I http://127.0.0.1/cp/
curl -fsS -u admin:monit http://127.0.0.1:2812/ | grep -m1 Monit
curl -X POST http://127.0.0.1:8888/mi \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"ps"}'
```