新网络,有点灵(二)
新网络,有点灵(二)
上文谈到了 vSRX 的快乐密钥,确实好用👍,但 vSRX 也会有些意想不到的问题。
爆発だ、BGP!
vSRX 的功能很丰富,BGP 自然是少不了的。但是接受全表之后迅速出现了一个问题:内存爆炸。我们可以增加内存条,NFX250 最大支持 4x16 GiB 的内存,但是 vSRX 的内存分配机制并不如我们想的那样,PFE 的核心内存是不变的。更为胡扯的是,一旦内存爆炸 packet 就会被胡乱 route,完全不像一个 security device. 万一 route 到了 NSA 监听的 switch 上去…… 信 息 泄 露 不 可 避
> show chassis routing-engine
Routing Engine status:
Total memory 131018 MB Max 61578 MB used ( 47 percent)
Control plane memory 65482 MB Max 7203 MB used ( 11 percent)
Data plane memory 65536 MB Max 53740 MB used ( 82 percent)
5 sec CPU utilization:
User 14 percent
Background 0 percent
Kernel 10 percent
Interrupt 0 percent
Idle 76 percent
Model VSRX RE
Start time 2023-06-06 18:33:08 UTC
Uptime 5 minutes, 54 seconds
Last reboot reason Router rebooted after a normal shutdown.
Load averages: 1 minute 5 minute 15 minute
1.50 1.46 0.73
> start shell pfe network fwdd
BSD platform (KVM virtual processor, 0MB memory, 16384KB flash)
FLOWD_VSRX(router-vsrx vty)# show memory
ID Base Total(b) Free(b) Used(b) % Name
-- ---------- ----------- ----------- ----------- --- -----------
0 20000000 536870912 429744320 107126592 19 Kernel
1 960000000 41070624768 4795215040 36275409728 88 User
PFE kernel 512MiB 的内存,不管怎样增大 VM 内存都不会改变。请教了 Soha,学到了一条很灵车的 crontab 可以修复这个问题:
# fuck 512M
@reboot sysctl -w hw.product.pvi.config.segment_mem_limit.kernel_heap=2048 && cli -c 'restart forwarding'
吼了!
> start shell pfe network fwdd
BSD platform (KVM virtual processor, 0MB memory, 16384KB flash)
FLOWD_VSRX(router-vsrx vty)# show memory
ID Base Total(b) Free(b) Used(b) % Name
-- ---------- ----------- ----------- ----------- --- -----------
0 20000000 2147483648 1407033856 740449792 34 Kernel
1 14bd90000 15370485760 296176832 15074308928 98 User
Landline
电信语音业务现在已经 IP 化了,一般来说全省的终端都在同一个 IPv4 大网下面,但是 IP 段是 squatted,接入了这个网便不能再轻易访问 Internet。如果你可以获得自己的接入密码,配置一下 Asterisk 便可以接听拨打电话。同其它服务器一样,我的 voice server 运行 Debian 11.
电信用的是一种非标准的 IMS 服务器。目前,Asterisk 推荐使用 chan_pjsip,但它与电信的兼容性不佳。因此,除了用回 chan_sip 之外,还需要对其进行一些修改。
以江苏电信为例,chan_sip 需要以下的配置:
host=js.ctcims.cn
username=+86[Area Code][Phone Number]@js.ctcims.cn
outboundproxy=p1szbac.js.ctcims.cn
secret=[Password]
type=peer
realm=js.ctcims.cn
allow=all
fromuser=+86[Area Code][Phone Number]
fromdomain=js.ctcims.cn
insecure=port,invite
permit=172.0.0.0/8
dtmfmode=auto
canreinvite=yes
电信的 INVITE 报头非标,少 field,我们只得修改 asterisk 源码:
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index a43908c..b87abd3 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -18575,8 +18575,16 @@ static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_re
Needs to be checked
*/
tmpf = ast_strdup(sip_get_header(req, "From"));
+ from = get_in_brackets(tmpf);
+ if( !strncasecmp(from, "tel:",4) ){
+ tmpf = ast_strdup(sip_get_header(req, "P-Asserted-Identity"));
+ from = get_in_brackets(tmpf); /* extract */
+ ast_log(LOG_NOTICE, "PATCH: Using P-Asserted-Identity: [%s]\n", from);
+ }
+
+
if (!ast_strlen_zero(tmpf)) {
- from = get_in_brackets(tmpf);
+ /* from = get_in_brackets(tmpf); */
if (parse_uri_legacy_check(from, "sip:,sips:,tel:", &from, NULL, &domain, NULL)) {
ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from);
return SIP_GET_DEST_INVALID_URI;
@@ -19499,6 +19507,7 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
{
char *of, *name, *unused_password, *domain;
RAII_VAR(char *, ofbuf, NULL, ast_free); /* beware, everyone starts pointing to this */
+ RAII_VAR(char *, ofbuf2, NULL, ast_free);
RAII_VAR(char *, namebuf, NULL, ast_free);
enum check_auth_result res = AUTH_DONT_KNOW;
char calleridname[256];
@@ -19507,6 +19516,12 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
terminate_uri(uri2); /* trim extra stuff */
ofbuf = ast_strdup(sip_get_header(req, "From"));
+ ofbuf2 = ast_strdup(sip_get_header(req, "From"));
+ if (!strncasecmp(get_in_brackets(ofbuf2), "tel:", 4)){
+ ast_log(LOG_NOTICE,"PATCH: Using 'P-Asserted-Identity', instead of [From <tel:>]\n");
+ ofbuf = ast_strdup(sip_get_header(req, "P-Asserted-Identity"));
+ }
+
/* XXX here tries to map the username for invite things */
/* strip the display-name portion off the beginning of the FROM header. */
diff --git a/channels/sip/reqresp_parser.c b/channels/sip/reqresp_parser.c
index dd730e9..9605446 100644
--- a/channels/sip/reqresp_parser.c
+++ b/channels/sip/reqresp_parser.c
@@ -70,6 +70,7 @@ int parse_uri_full(char *uri, const char *scheme, char **user, char **pass,
if (ast_strlen_zero(uri)) {
return -1;
}
+ ast_debug(1, "PARSING URI '%s'\n", uri);
if (scheme) {
int l;
@@ -127,7 +128,8 @@ int parse_uri_full(char *uri, const char *scheme, char **user, char **pass,
} else {
ast_debug(1, "No RFC 3966 global number or context found in '%s'; returning local number anyway\n", uri);
userinfo = uri; /* Return local number anyway */
- error = -1;
+ // error = -1;
+ *hostport = ast_strdup("+86"); // fixing CT non-standard header
}
} else {
char *dom = "";
执行 apt source asterisk=1:16.28.0~dfsg-0+deb11u3
拉下 asterisk 源码,然后将 diff apply 到 source tree 当中,最后 debuild -i -uc -us -b
,将生成的 deb 包悉数 dpkg -i
,最后启动 Asterisk,吼了!
Internet?
说到 asterisk 服务器的网卡,接到电信的是一张 squatted 的 IPv4 大网,这张网同 internet 不互通,在这上面,所有的 IP 地址都是电信自由分配的。拨入的 IP 是什么都有可能。如果我们的机器想要访问 internet,便不能通过 voice eth. 哪怕我们再加上一个 internet eth,路由也没法做。
但路也不是绝对走不通,想想我们这台服务器都需要访问 internet 的什么内容?无非就是 apt,或者 SSH. 如此便可以配置 policy routing,将几个特定端口从 internet eth 路由出去,而其他流量将继续走 voice eth.
配置的方法也很简单,Debian 默认使用 Network Manager,这样只需要修改 /etc/NetworkManager/dispatcher.d/rules
文件,在 if-up 的时候添加 ip rule 便可:
#!/usr/bin/env bash
set -x
interface=$1
event=$2
# eth0 is internet eth, eth1 is voice eth
if [[ $interface != "eth0" ]] || [[ $event != "up" ]]
then
return 0
fi
ip route flush table 100
ip route add default via [InternetGateway] table 100
ip route add [InternetEthNetwork] dev eth0 table 100
ip rule flush table 100
ip rule add sport 22 table 100
ip rule add dport 22 table 100
ip rule add sport 80 table 100
ip rule add sport 443 table 100
ip rule add dport 80 table 100
ip rule add dport 443 table 100
如此,所有的 SSH/HTTP/HTTPS packet 都会从 internet eth 走了。除此以外,我们还需要配置 DNS server,因为注册 IMS 的时候,需要解析电信的域名 js.ctcims.cn
到 IP。这里可以选择较为灵活的 Dnsmasq 来解析,只需要将上游 DNS pin 在 internet eth,配置几个电信的 entry (/etc/dnsmasq.d/00-ctcims.cn
),就万事大吉了。记得 dig 一下电信的 voice DNS 获取一下下面需要的 IP.
server=/js.ctcims.cn/[IP1]
server=/js.ctcims.cn/[IP2]
address=/blackhole.ctcims.cn/127.0.0.1
srv-host=_sip._udp.js.ctcims.cn,[IP1],5060,0,0
srv-host=_sip._udp.js.ctcims.cn,[IP2],5060,1,0
PPPoE/IPv6-PD
PPPoE 没有任何难度。简单配置即可。只是 IPv6 PD 有点小麻烦,这个配置大多数时候可以用,但是 PD 过期的时候偶尔抽风。不过没关系,难道你真的在用 IPv6?
记得把 PD 参数改成当地的 (•᎑<)ー☆ 我这里电信和移动的 PD 参数竟然一样!
interfaces {
pp0 {
unit 0 {
description "China Telecom";
ppp-options {
chap {
default-chap-secret "YOUR_LITTLE_SECRET!"; ## SECRET-DATA
local-name YOUR_LITTLE_SECRET!;
no-rfc2486;
passive;
}
pap {
default-password "YOUR_LITTLE_SECRET!"; ## SECRET-DATA
local-name YOUR_LITTLE_SECRET!;
no-rfc2486;
local-password "YOUR_LITTLE_SECRET!"; ## SECRET-DATA
passive;
}
initiate-ncp {
ipv6;
}
}
pppoe-options {
underlying-interface ge-0/0/8.0;
idle-timeout 0;
auto-reconnect 3;
client;
}
family inet {
negotiate-address;
}
family inet6 {
dhcpv6-client {
client-type stateful;
client-ia-type ia-pd;
rapid-commit;
prefix-delegating {
preferred-prefix-length 60;
sub-prefix-length 64;
}
client-identifier duid-type duid-llt;
req-option dns-server;
req-option domain;
retransmission-attempt 5;
update-router-advertisement {
interface ge-0/0/6.100 {
other-stateful-configuration;
max-advertisement-interval 180;
}
interface lo0.3 {
other-stateful-configuration;
}
}
update-server;
}
}
}
unit 1 {
description "China Mobile";
ppp-options {
chap {
default-chap-secret "YOUR_LITTLE_SECRET!"; ## SECRET-DATA
local-name YOUR_LITTLE_SECRET!;
no-rfc2486;
passive;
}
pap {
default-password "YOUR_LITTLE_SECRET!"; ## SECRET-DATA
local-name YOUR_LITTLE_SECRET!;
no-rfc2486;
local-password "YOUR_LITTLE_SECRET!"; ## SECRET-DATA
passive;
}
initiate-ncp {
ipv6;
}
}
pppoe-options {
underlying-interface ge-0/0/7.0;
idle-timeout 0;
auto-reconnect 3;
client;
}
family inet {
negotiate-address;
}
family inet6 {
dhcpv6-client {
client-type stateful;
client-ia-type ia-pd;
rapid-commit;
prefix-delegating {
preferred-prefix-length 60;
sub-prefix-length 64;
}
client-identifier duid-type duid-llt;
req-option dns-server;
req-option domain;
retransmission-attempt 5;
update-router-advertisement {
interface ge-0/0/6.101 {
other-stateful-configuration;
max-advertisement-interval 180;
}
interface lo0.2 {
other-stateful-configuration;
}
}
update-server;
}
}
}
}
}
event-options {
policy DHCPv6fixCT {
events SNMP_TRAP_LINK_UP;
attributes-match {
SNMP_TRAP_LINK_UP.interface-name matches pp0.0;
}
then {
execute-commands {
commands {
"request dhcpv6 client renew interface pp0.0";
}
user-name afa;
}
}
}
policy DHCPv6fixCM {
events SNMP_TRAP_LINK_UP;
attributes-match {
SNMP_TRAP_LINK_UP.interface-name matches pp0.1;
}
then {
execute-commands {
commands {
"request dhcpv6 client renew interface pp0.1";
}
user-name afa;
}
}
}
}