Hi,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system. I was able to create and run the containers successfully, they are starting and listening to the correct ports, but for some unexplained reason - the incoming SIP traffic is not getting picked up by Kamailio. I can easily trace the traffic from the host, but when SSHing the container and running a test from within, no traffic goes by. I've used netcat to generate plain UDP traffic to the container, and it was logged into the Kamailio log files, but real-life traffic doesn't seem to work. I've tried moving to host mode (from bridge), but it didn't make any difference. All required firewall rules were opened obviously, I've also tried shutting the firewall off completely but it didn't help.
Does anyone experienced anything similar while running Kamailio in Dockers, and could provide me a go-through on what steps did he take to fix it?
EXCERPT FROM MY DOCKERFILE
# Getting Kamailio source code from GIT RUN mkdir -p /usr/local/src/kamailio-5.3 WORKDIR /usr/local/src/kamailio-5.3 RUN git clone --depth 1 --no-single-branch https://github.com/kamailio/kamailio WORKDIR /usr/local/src/kamailio-5.3/kamailio RUN git checkout -b 5.3.2
# Compile the source code and install Kamailio RUN make include_modules="phonenum db_mysql xmlrpc http_async_client jansson auth_db nathelper websocket tls outbound topoh http_client" cfg && \ make all && make install
# Default setting is to run Kamailio as user “kamailio” and group “kamailio” RUN adduser --quiet --system --group --disabled-password \ --shell /bin/false --gecos "Kamailio" \ --home /var/run/kamailio kamailio
# To use init.d script for starting/stopping the Kamailio server COPY Init/kamailio /etc/init.d/ RUN chmod 755 /etc/init.d/kamailio COPY Default/kamailio /etc/default/ COPY kamailio.service /etc/systemd/system/ RUN mkdir -p /var/run/kamailio RUN chown kamailio:kamailio /var/run/kamailio
COMPOSE (BRIDGE NETWORK VERSION)
kamailioegress: build: kamailio_egress image: kamailioegress:latest container_name: kamailioegress restart: always environment: - DATABASE=kamailioe - SIP_DOMAIN=XXX - DBHOST=kamailiodb - DBROOTUSER=root - DBROOTPASS=XXX - PUBLIC_IPV4=XXX depends_on: - Kamailio-Base - kmdb - freeswitch - rtpengine expose: - "5060/udp" - "5060/tcp" ports: - "XXX:5060:5060/udp" networks: private-net: ipv4_address: "172.18.0.30" deploy: mode: replicated replicas: 1 restart_policy: condition: always delay: 5s max_attempts: 3 window: 120s
networks: private-net: driver: bridge ipam: config: - subnet: 172.18.0.0/16 driver_opts: com.docker.network.bridge.name: wrtcpriv public-net: external: name: host
COMPOSE (HOST MODE VERSION)
kamailioegress: build: kamailio_egress image: kamailioegress:latest container_name: kamailioegress network_mode: host restart: always environment: - DATABASE=kamailioe - SIP_DOMAIN=XXX - DBHOST=172.18.0.10 - DBROOTUSER=root - DBROOTPASS=XXX - PUBLIC_IPV4=XXX - EGPORT=5060 - LINTE=ens224 - LINTI=ens192 - RTPENGINE=localhost depends_on: - Kamailio-Base - kmdb - freeswitch - rtpengine expose: - "5060/udp" ports: - "213.8.76.13:5060:5060/udp" deploy: mode: replicated replicas: 1 restart_policy: condition: always delay: 5s max_attempts: 3 window: 120s
CONFIG FILE
/* uncomment and configure the following line if you want Kamailio to * bind on a specific interface/port/proto (default bind on all available) */ listen=udp:0.0.0.0:LPORT advertise PUBLIC_IP:LPORT
KAMAILIO-LOCALE
#!define DBURL "mysql://root:XXX@DBHOST/kamailioe" #!substdef "!MY_DBURL!mysql://root:XXX@DBHOST/kamailioe!g" #!substdef "!RTPENGINE!MY_RTPENGINE!g" #!substdef "!SIP_DOMAIN!MY_SIP_DOMAIN!g" #!substdef "!PUBLIC_IP!MY_PUBLIC_IP!g" #!substdef "!PRIVATE_IP!MY_PRIVATE_IP!g" #!substdef "!LPORT!MY_LPORT!g" #!substdef "!LINT!MY_LINT!g" #!substdef "!HOMER_IP!10.1.0.100!g" #!substdef "!API_URL!http://localhost:3000/v1/mock!g" #!substdef "/CCODES/972|380/" #!substdef "/NUM_TRANSLATE_OUT_RE/\\+?(CCODES)([0-9]+)/" #!substdef "/NUM_TRANSLATE_IN_RE/0([0-9]+)/"
FIREWALL RULES
-bash-4.2# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens192 ens224 sources: 192.168.1.39 services: dhcpv6-client http https sip ssh ports: 9323/tcp 9323/udp protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" destination address="XXX" port port="5060" protocol="udp" accept rule family="ipv4" destination address="XXX" port port="5060" protocol="tcp" accept
NETSTAT OUTPUT Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 XXX:5060 0.0.0.0:* 22479/kamailio
Edward
Issue documented here https://github.com/moby/libnetwork/issues/2423
you can use
/usr/bin/docker run --net=host --privileged --rm claesjonsson/conntrack -D --proto udp
On Mon, Jul 27, 2020 at 10:28 AM Edward Romanenco edward@telemessage.com wrote:
Hi,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system. I was able to create and run the containers successfully, they are starting and listening to the correct ports, but for some unexplained reason - the incoming SIP traffic is not getting picked up by Kamailio. I can easily trace the traffic from the host, but when SSHing the container and running a test from within, no traffic goes by. I've used netcat to generate plain UDP traffic to the container, and it was logged into the Kamailio log files, but real-life traffic doesn't seem to work. I've tried moving to host mode (from bridge), but it didn't make any difference. All required firewall rules were opened obviously, I've also tried shutting the firewall off completely but it didn't help.
Does anyone experienced anything similar while running Kamailio in Dockers, and could provide me a go-through on what steps did he take to fix it?
EXCERPT FROM MY DOCKERFILE
# Getting Kamailio source code from GIT RUN mkdir -p /usr/local/src/kamailio-5.3 WORKDIR /usr/local/src/kamailio-5.3 RUN git clone --depth 1 --no-single-branch https://github.com/kamailio/kamailio WORKDIR /usr/local/src/kamailio-5.3/kamailio RUN git checkout -b 5.3.2
# Compile the source code and install Kamailio RUN make include_modules="phonenum db_mysql xmlrpc http_async_client jansson auth_db nathelper websocket tls outbound topoh http_client" cfg && \ make all && make install
# Default setting is to run Kamailio as user “kamailio” and group “kamailio” RUN adduser --quiet --system --group --disabled-password \ --shell /bin/false --gecos "Kamailio" \ --home /var/run/kamailio kamailio
# To use init.d script for starting/stopping the Kamailio server COPY Init/kamailio /etc/init.d/ RUN chmod 755 /etc/init.d/kamailio COPY Default/kamailio /etc/default/ COPY kamailio.service /etc/systemd/system/ RUN mkdir -p /var/run/kamailio RUN chown kamailio:kamailio /var/run/kamailio
COMPOSE (BRIDGE NETWORK VERSION)
kamailioegress: build: kamailio_egress image: kamailioegress:latest container_name: kamailioegress restart: always environment: - DATABASE=kamailioe - SIP_DOMAIN=XXX - DBHOST=kamailiodb - DBROOTUSER=root - DBROOTPASS=XXX - PUBLIC_IPV4=XXX depends_on: - Kamailio-Base - kmdb - freeswitch - rtpengine expose: - "5060/udp" - "5060/tcp" ports: - "XXX:5060:5060/udp" networks: private-net: ipv4_address: "172.18.0.30" deploy: mode: replicated replicas: 1 restart_policy: condition: always delay: 5s max_attempts: 3 window: 120s
networks: private-net: driver: bridge ipam: config: - subnet: 172.18.0.0/16 driver_opts: com.docker.network.bridge.name: wrtcpriv public-net: external: name: host
COMPOSE (HOST MODE VERSION)
kamailioegress: build: kamailio_egress image: kamailioegress:latest container_name: kamailioegress network_mode: host restart: always environment: - DATABASE=kamailioe - SIP_DOMAIN=XXX - DBHOST=172.18.0.10 - DBROOTUSER=root - DBROOTPASS=XXX - PUBLIC_IPV4=XXX - EGPORT=5060 - LINTE=ens224 - LINTI=ens192 - RTPENGINE=localhost depends_on: - Kamailio-Base - kmdb - freeswitch - rtpengine expose: - "5060/udp" ports: - "213.8.76.13:5060:5060/udp" deploy: mode: replicated replicas: 1 restart_policy: condition: always delay: 5s max_attempts: 3 window: 120s
CONFIG FILE
/* uncomment and configure the following line if you want Kamailio to
- bind on a specific interface/port/proto (default bind on all available) */
listen=udp:0.0.0.0:LPORT advertise PUBLIC_IP:LPORT
KAMAILIO-LOCALE
#!define DBURL "mysql://root:XXX@DBHOST/kamailioe" #!substdef "!MY_DBURL!mysql://root:XXX@DBHOST/kamailioe!g" #!substdef "!RTPENGINE!MY_RTPENGINE!g" #!substdef "!SIP_DOMAIN!MY_SIP_DOMAIN!g" #!substdef "!PUBLIC_IP!MY_PUBLIC_IP!g" #!substdef "!PRIVATE_IP!MY_PRIVATE_IP!g" #!substdef "!LPORT!MY_LPORT!g" #!substdef "!LINT!MY_LINT!g" #!substdef "!HOMER_IP!10.1.0.100!g" #!substdef "!API_URL!http://localhost:3000/v1/mock!g" #!substdef "/CCODES/972|380/" #!substdef "/NUM_TRANSLATE_OUT_RE/\\+?(CCODES)([0-9]+)/" #!substdef "/NUM_TRANSLATE_IN_RE/0([0-9]+)/"
FIREWALL RULES
-bash-4.2# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens192 ens224 sources: 192.168.1.39 services: dhcpv6-client http https sip ssh ports: 9323/tcp 9323/udp protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" destination address="XXX" port port="5060" protocol="udp" accept rule family="ipv4" destination address="XXX" port port="5060" protocol="tcp" accept
NETSTAT OUTPUT Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 XXX:5060 0.0.0.0:* 22479/kamailio
Edward
Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
Hey guys,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system.
Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.
For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?
v=0. o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 45878 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16
Edward
Hello,
the mangler module does not have any idea of inbound/outbound directions, so you can use it for any of them.
Also, the nathelper module should have a function allowing to change the ip in the sdp, iirc.
On the other hand, if you use rtppengine for the calls, then the ips should be replaced by it.
Do not forget to use msg_apply_changes() in case you want those changes to be visible immediately in the configuration file.
Cheers, Daniel
On 29.07.20 13:18, Edward Romanenco wrote:
Hey guys,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system.
Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.
For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?
v=0. o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 45878 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16
Edward
Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
It looks like rtpengine has to be a bridge between docker-compose network and external ( for docker compose ) net.
First of all there is an option of rrpengine to listen 2 interfaces, which can be the same interface but one of them can be advertised to external ip. So you can give aliases to those virtual interfaces and use flag "direction" when call rtpengine module in kamailio.
Also you can use "media-addr" flag when call rtpengine module instead using direction flag, this is more flexible but more tricky.
On Tue, 4 Aug 2020, 10:30 Daniel-Constantin Mierla, miconda@gmail.com wrote:
Hello,
the mangler module does not have any idea of inbound/outbound directions, so you can use it for any of them.
Also, the nathelper module should have a function allowing to change the ip in the sdp, iirc.
On the other hand, if you use rtppengine for the calls, then the ips should be replaced by it.
Do not forget to use msg_apply_changes() in case you want those changes to be visible immediately in the configuration file.
Cheers, Daniel
On 29.07.20 13:18, Edward Romanenco wrote:
Hey guys,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system .
Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.
For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?
v=0. o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 45878 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16
Edward
Kamailio (SER) - Users Mailing Listsr-users@lists.kamailio.orghttps://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
-- Daniel-Constantin Mierla -- www.asipto.comwww.twitter.com/miconda -- www.linkedin.com/in/miconda Funding: https://www.paypal.me/dcmierla
Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
I tried using nathelper in the following way - fix_nated_sdp("2","XX.XX.XX.XX"); - it still shows my internal IP. Attaching my request routes, can you kindly check and see if I am using it correctly?
SDP . v=0. o=FreeSWITCH 1596486133 1596486134 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 43954 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16. a=ptime:20.
REQUEST ROUTES request_route { setflag(22); route(REQINIT);
if (is_method("CANCEL")) { if (t_check_trans()) { route(RELAY); } exit; }
route(WITHINDLG);
if(t_precheck_trans()) { t_check_trans(); exit; } t_check_trans();
remove_hf("Route"); if (is_method("INVITE|SUBSCRIBE")){// && is_present_hf("X-SESSION-ID")){ record_route(); } if (is_method("INVITE")) { setflag(FLT_ACC); }
if ($rU==$null) { sl_send_reply("484","Address Incomplete"); exit; }
route(OUTGOING); route(PSTN); route(INCOMING); route(RELAY); }
route[REMOVE_X_HEADERS] { if(is_present_hf("X-SESSION-ID")) { remove_hf("X-FS-Support"); remove_hf("X-Src"); remove_hf("X-DESTINATIONS"); remove_hf("X-SESSION-ID"); } xinfo("Remove X Headers; Contact Header is $ct"); }
route[INCOMING] { if(is_present_hf("X-SESSION-ID")) { return; }
if(ds_is_from_list("4")) { route(TRANSLATE_SRC_IN); }
route(REQUEST_PERMISSIONS); fix_nated_sdp("2","XX.XX.XX.XX"); exit; }
route[REQUEST_PERMISSIONS] { $var(body) = 0; $var(from) = $fU;
if($(var(from){s.substr,1,4})=="0972") { $var(from)=$(var(from){s.substr,2,0}); $fU = $var(from); }
jansson_set("string", "from", "$var(from)", "$var(body)");
if(is_present_hf("Diversion")) { xlog("L_INFO", "Call has been forwarded."); jansson_set("string","to","$oU","$var(body)"); } else { jansson_set("string","to","$tU","$var(body)"); }
jansson_set("string","forcepstn","false","$var(body)"); jansson_set("string", "source", "EGRESS", "$var(body)"); $http_req(all) = $null; $http_req(method) = "POST"; $http_req(hdr) = "Content-Type: application/json"; $http_req(hdr) = "Accept: application/json"; $http_req(hdr) = "Connection: keep-alive"; $http_req(body) = $var(body); $var(re_url)= "https://VNVHOST/voiceandvideo/makeCall"; t_newtran();
if (http_async_query("$var(re_url)", "REQUEST_PERMISSIONS_REPLY") < 0) { t_reply("500", "Server Internal Error"); exit; } }
route[REQUEST_PERMISSIONS_REPLY] { if ($(http_err{s.len})) { xlog("L_ERR","Got error from server 1"); t_reply("500", "Server Internal Error"); exit; } else if ($http_rs != 200) { xlog("L_ERR","Got error from server 2"); t_reply("500", "Server Error"); exit; }
# Populate dialog variables for CDR Creation $var(count) = 0; jansson_get("list",$http_rb,"$dlg_var(destinations_array)"); jansson_get("msgID", $http_rb, "$dlg_var(session_id)"); jansson_get("resultCode",$http_rb,"$dlg_var(resultCode)");
if($dlg_var(resultCode)!=0) { t_reply("500","Server Internal Error"); exit; }
## EGRESS Server Information route(ADD_TELEMESSAGE_HDRS); $var(setid) = "1";
if(!ds_select_dst("1", "4")) { send_reply("404", "No destination"); exit; }
route(RELAY); exit; }
route[RELAY] { if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { if(!t_is_set("branch_route")) { t_on_branch("MANAGE_BRANCH"); } }
if (is_method("INVITE|SUBSCRIBE|UPDATE")) { if(!t_is_set("onreply_route")) { t_on_reply("MANAGE_REPLY"); } } if (is_method("INVITE")) { if(!t_is_set("failure_route")) { t_on_failure("MANAGE_FAILURE"); } }
if (!t_relay()) { sl_reply_error(); }
exit; }
# Per SIP request initial checks route[REQINIT] { #!ifdef WITH_ANTIFLOOD # flood detection from same IP and traffic ban for a while # be sure you exclude checking trusted peers, such as pstn gateways # - local host excluded (e.g., loop to self) if(src_ip!=myself) { if($sht(ipban=>$si)!=$null) { # ip is already blocked xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); exit; } if (!pike_check_req()) { xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); $sht(ipban=>$si) = 1; exit; } } #!endif if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") { # silent drop for scanners - uncomment next line if want to reply # sl_send_reply("200", "OK"); exit; }
if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; }
if(is_method("OPTIONS") && uri==myself && $rU==$null) { sl_send_reply("200","Keepalive"); exit; }
if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } }
# Handle requests within SIP dialogs route[WITHINDLG] { xlog("L_ERR","Entering withindlgs"); if (!has_totag()) return;
# sequential request withing a dialog should # take the path determined by record-routing if (loose_route()) { xlog("L_ERR","loose route"); route(DLGURI); if (is_method("BYE")) { xlog("L_ERR","BYE recevied in loose route"); setflag(FLT_ACC); # do accounting ... setflag(FLT_ACCFAILED); # ... even if the transaction fails } else if ( is_method("ACK") ) { # ACK is forwarded statelessly route(NATMANAGE); } else if ( is_method("NOTIFY") ) { # Add Record-Route for in-dialog NOTIFY as per RFC 6665. xlog("L_ERR","*****************1 Adding rr"); record_route(); }
route(RELAY); exit; }
if (is_method("SUBSCRIBE") && uri == myself) { # in-dialog subscribe requests route(PRESENCE); exit; } if ( is_method("ACK") ) { if ( t_check_trans() ) { # no loose-route, but stateful ACK; # must be an ACK after a 487 # or e.g. 404 from upstream server route(RELAY); exit; } else { # ACK without matching transaction ... ignore and discard exit; } } sl_send_reply("404","Not here"); exit; }
# Handle SIP registrations route[REGISTRAR] { if (!is_method("REGISTER")) return;
if(isflagset(FLT_NATS)) { setbflag(FLB_NATB); #!ifdef WITH_NATSIPPING # do SIP NAT pinging setbflag(FLB_NATSIPPING); #!endif } if (!save("location")) { sl_reply_error(); } exit; }
# User location service route[LOCATION] {
#!ifdef WITH_SPEEDDIAL # search for short dialing - 2-digit extension if($rU=~"^[0-9][0-9]$") { if(sd_lookup("speed_dial")) { route(SIPOUT); } } #!endif
#!ifdef WITH_ALIASDB # search in DB-based aliases if(alias_db_lookup("dbaliases")) { route(SIPOUT); } #!endif
$avp(oexten) = $rU; if (!lookup("location")) { $var(rc) = $rc; route(TOVOICEMAIL); t_newtran(); switch ($var(rc)) { case -1: case -3: send_reply("404", "Not Found"); exit; case -2: send_reply("405", "Method Not Allowed"); exit; } }
if (is_method("INVITE")) { setflag(FLT_ACCMISSED); }
route(RELAY); exit; }
# Presence server processing route[PRESENCE] { if(!is_method("PUBLISH|SUBSCRIBE")) return;
if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { route(TOVOICEMAIL); # returns here if no voicemail server is configured sl_send_reply("404", "No voicemail service"); exit; }
#!ifdef WITH_PRESENCE if (!t_newtran()) { sl_reply_error(); exit; }
if(is_method("PUBLISH")) { handle_publish(); t_release(); } else if(is_method("SUBSCRIBE")) { handle_subscribe(); t_release(); } exit; #!endif
# if presence enabled, this part will not be executed if (is_method("PUBLISH") || $rU==$null) { sl_send_reply("404", "Not here"); exit; } return; }
# IP authorization and user authentication route[AUTH] { #!ifdef WITH_AUTH
#!ifdef WITH_IPAUTH if((!is_method("REGISTER")) && allow_source_address()) { # source IP allowed return; } #!endif
if (is_method("REGISTER") || from_uri==myself) { # authenticate requests if (!auth_check("$fd", "subscriber", "1")) { auth_challenge("$fd", "0"); exit; } # user authenticated - remove auth header if(!is_method("REGISTER|PUBLISH")) consume_credentials(); } # if caller is not local subscriber, then check if it calls # a local destination, otherwise deny, not an open relay here if (from_uri!=myself && uri!=myself) { sl_send_reply("403","Not relaying"); exit; }
#!endif return; }
# Caller NAT detection route[NATDETECT] { #!ifdef WITH_NAT force_rport(); if (nat_uac_test("19")) { if (is_method("REGISTER")) { fix_nated_register(); } else { if(is_first_hop()) { set_contact_alias(); } } setflag(FLT_NATS); } #!endif return; }
# RTPProxy control and signaling updates for NAT traversal route[NATMANAGE] { #!ifdef WITH_NAT if (is_request()) { if(has_totag()) { if(check_route_param("nat=yes")) { setbflag(FLB_NATB); } } } if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return;
if(nat_uac_test("8")) { if(ds_is_from_list()){ xdbg("__META rtpengine priv->pub"); rtpengine_manage("replace-session-connection replace-origin direction=priv direction=pub"); } else { xdbg("__META rtpengine pub->priv"); rtpengine_manage("replace-session-connection replace-origin direction=pub direction=priv"); } } else { if(ds_is_from_list()) { xdbg("__META rtpengine priv->pub"); rtpengine_manage("replace-session-connection replace-origin trust-address direction=priv direction=pub"); } else { xdbg("__META rtpengine pub->priv"); rtpengine_manage("replace-session-connection replace-origin trust-address direction=pub direction=priv"); } }
if (is_request()) { if (!has_totag()) { if(t_is_branch_route()) { add_rr_param(";nat=yes"); } } }
if (is_reply()) { if(isbflagset(FLB_NATB)) { if(is_first_hop()) set_contact_alias(); } xlog("L_ERR","20202020 in is_reply"); } #!endif return; }
# URI update for dialog requests route[DLGURI] { #!ifdef WITH_NAT if(!isdsturiset()) { handle_ruri_alias(); } #!endif return; }
# Routing to foreign domains route[SIPOUT] { if (uri==myself) return; append_hf("P-hint: outbound\r\n"); route(RELAY); exit; }
# PSTN GW routing route[PSTN] { #!ifdef WITH_PSTN # check if PSTN GW IP is defined if (strempty($sel(cfg_get.pstn.gw_ip))) { xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); return; }
# route to PSTN dialed numbers starting with '+' or '00' # (international format) # - update the condition to match your dialing rules for PSTN routing if(!($rU=~"^(+|00)[1-9][0-9]{3,20}$")) return;
# only local users allowed to call if(from_uri!=myself) { sl_send_reply("403", "Not Allowed"); exit; }
if (strempty($sel(cfg_get.pstn.gw_port))) { $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); } else { $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" + $sel(cfg_get.pstn.gw_port); }
route(RELAY); exit; #!endif
return; }
# XMLRPC routing #!ifdef WITH_XMLRPC route[XMLRPC] { # allow XMLRPC from localhost if ((method=="POST" || method=="GET") && (src_ip==127.0.0.1)) { # close connection only for xmlrpclib user agents (there is a bug in # xmlrpclib: it waits for EOF before interpreting the response). if ($hdr(User-Agent) =~ "xmlrpclib") set_reply_close(); set_reply_no_connect(); dispatch_rpc(); exit; } send_reply("403", "Forbidden"); exit; } #!endif
# Routing to voicemail server route[TOVOICEMAIL] { #!ifdef WITH_VOICEMAIL if(!is_method("INVITE|SUBSCRIBE")) return;
# check if VoiceMail server IP is defined if (strempty($sel(cfg_get.voicemail.srv_ip))) { xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); return; } if(is_method("INVITE")) { if($avp(oexten)==$null) return;
$ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) + ":" + $sel(cfg_get.voicemail.srv_port); } else { if($rU==$null) return;
$ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) + ":" + $sel(cfg_get.voicemail.srv_port); } route(RELAY); exit; #!endif
return; }
//convert phone number from international to internal //+972112223344 <-> 011222334 route[TRANSLATE_DST_OUT] { xinfo("__META TRANSLATE_DST_OUT"); xdbg("__META To: $hdr(To)"); xdbg("__META Regexp: NUM_TRANSLATE_OUT_RE");
if(subst_uri("/NUM_TRANSLATE_OUT_RE/0\2/")) xdbg("__META URI translated"); else xdbg("__META Not translating number in URI");
if(subst_hf("To", "/NUM_TRANSLATE_OUT_RE/0\2/", "a")) xdbg("__META To header translated"); else xdbg("__META Not translating number in to header"); }
//convert phone number from internal format to international //011222334 <-> +<972>112223344 route[TRANSLATE_SRC_IN] { $var(number)=$rU; if($(var(number){s.substr,1,4})=="+972") { $rU="0"+$(var(number){s.substr,5,0}); } } /////////////////////////////////////////////////////////////////////////////
# Manage outgoing branches branch_route[MANAGE_BRANCH] { xdbg("new branch [$T_branch_idx] to $ru\n"); route(NATMANAGE); }
# Manage incoming replies onreply_route[MANAGE_REPLY] { xdbg("incoming reply\n");
// fix_nated_contact(); xlog("L_ERR","2020202020202 Got reply $ct");
if(status=~"[12][0-9][0-9]") { route(NATMANAGE); }
if(is_method("INVITE") && is_present_hf("P-Asserted-Identity")) { remove_hf("P-Asserted-Identity"); } }
# Manage failure routing cases failure_route[MANAGE_FAILURE] { xlog("Failure! Going to failure route."); route(NATMANAGE); if (t_is_canceled()) exit;
#!ifdef WITH_BLOCK3XX # block call redirect based on 3xx replies. if (t_check_status("3[0-9][0-9]")) { t_reply("404","Not found"); exit; } #!endif
#!ifdef WITH_BLOCK401407 # block call redirect based on 401, 407 replies. if (t_check_status("401|407")) { t_reply("404","Not found"); exit; } #!endif
#!ifdef WITH_VOICEMAIL # serial forking # - route to voicemail on busy or no answer (timeout) if (t_check_status("486|408")) { $du = $null; route(TOVOICEMAIL); exit; } #!endif }
event_route[topoh:msg-outgoing] { if($sndto(ip)=="freeswitch") { drop; } if($sndto(ip)=="81.24.193.248") { drop; } }
Edward ________________________________ From: Daniel-Constantin Mierla miconda@gmail.com Sent: Tuesday, August 4, 2020 11:19 AM To: Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org; Edward Romanenco edward@telemessage.com Subject: Re: [SR-Users] Manipulating SDP IP for Inbound Calls
Hello,
the mangler module does not have any idea of inbound/outbound directions, so you can use it for any of them.
Also, the nathelper module should have a function allowing to change the ip in the sdp, iirc.
On the other hand, if you use rtppengine for the calls, then the ips should be replaced by it.
Do not forget to use msg_apply_changes() in case you want those changes to be visible immediately in the configuration file.
Cheers, Daniel
On 29.07.20 13:18, Edward Romanenco wrote: Hey guys,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system.
Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.
For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?
v=0. o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 45878 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16
Edward
_______________________________________________ Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
-- Daniel-Constantin Mierla -- www.asipto.comhttp://www.asipto.com www.twitter.com/micondahttp://www.twitter.com/miconda -- www.linkedin.com/in/micondahttp://www.linkedin.com/in/miconda Funding: https://www.paypal.me/dcmierla
Hello,
hard to track the execution path without a test environment ... I would suggest to load debugger module and enable cfgtrace for it to see what actions in configuration file are executed, to be sure it gets to the fix_nated_sdp().
Cheers, Daniel
On 04.08.20 10:44, Edward Romanenco wrote:
I tried using nathelper in the following way - fix_nated_sdp("2","XX.XX.XX.XX"); - it still shows my internal IP. Attaching my request routes, can you kindly check and see if I am using it correctly?
*SDP* . v=0. o=FreeSWITCH 1596486133 1596486134 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 43954 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16. a=ptime:20.
*REQUEST ROUTES* request_route { setflag(22); route(REQINIT);
if (is_method("CANCEL")) { if (t_check_trans()) { route(RELAY); } exit; }
route(WITHINDLG);
if(t_precheck_trans()) { t_check_trans(); exit; } t_check_trans();
remove_hf("Route"); if (is_method("INVITE|SUBSCRIBE")){// && is_present_hf("X-SESSION-ID")){ record_route(); } if (is_method("INVITE")) { setflag(FLT_ACC); }
if ($rU==$null) { sl_send_reply("484","Address Incomplete"); exit; }
route(OUTGOING); route(PSTN); route(INCOMING); route(RELAY); }
route[REMOVE_X_HEADERS] { if(is_present_hf("X-SESSION-ID")) { remove_hf("X-FS-Support"); remove_hf("X-Src"); remove_hf("X-DESTINATIONS"); remove_hf("X-SESSION-ID"); } xinfo("Remove X Headers; Contact Header is $ct"); }
route[INCOMING] { if(is_present_hf("X-SESSION-ID")) { return; }
if(ds_is_from_list("4")) { route(TRANSLATE_SRC_IN); }
route(REQUEST_PERMISSIONS); fix_nated_sdp("2","XX.XX.XX.XX"); exit; }
route[REQUEST_PERMISSIONS] { $var(body) = 0; $var(from) = $fU;
if($(var(from){s.substr,1,4})=="0972") { $var(from)=$(var(from){s.substr,2,0}); $fU = $var(from); }
jansson_set("string", "from", "$var(from)", "$var(body)");
if(is_present_hf("Diversion")) { xlog("L_INFO", "Call has been forwarded."); jansson_set("string","to","$oU","$var(body)"); } else { jansson_set("string","to","$tU","$var(body)"); }
jansson_set("string","forcepstn","false","$var(body)"); jansson_set("string", "source", "EGRESS", "$var(body)"); $http_req(all) = $null; $http_req(method) = "POST"; $http_req(hdr) = "Content-Type: application/json"; $http_req(hdr) = "Accept: application/json"; $http_req(hdr) = "Connection: keep-alive"; $http_req(body) = $var(body); $var(re_url)= "https://VNVHOST/voiceandvideo/makeCall"; t_newtran();
if (http_async_query("$var(re_url)", "REQUEST_PERMISSIONS_REPLY") < 0) { t_reply("500", "Server Internal Error"); exit; } }
route[REQUEST_PERMISSIONS_REPLY] { if ($(http_err{s.len})) { xlog("L_ERR","Got error from server 1"); t_reply("500", "Server Internal Error"); exit; } else if ($http_rs != 200) { xlog("L_ERR","Got error from server 2"); t_reply("500", "Server Error"); exit; }
# Populate dialog variables for CDR Creation $var(count) = 0; jansson_get("list",$http_rb,"$dlg_var(destinations_array)"); jansson_get("msgID", $http_rb, "$dlg_var(session_id)"); jansson_get("resultCode",$http_rb,"$dlg_var(resultCode)");
if($dlg_var(resultCode)!=0) { t_reply("500","Server Internal Error"); exit; }
## EGRESS Server Information route(ADD_TELEMESSAGE_HDRS); $var(setid) = "1";
if(!ds_select_dst("1", "4")) { send_reply("404", "No destination"); exit; }
route(RELAY); exit; }
route[RELAY] { if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { if(!t_is_set("branch_route")) { t_on_branch("MANAGE_BRANCH"); } }
if (is_method("INVITE|SUBSCRIBE|UPDATE")) { if(!t_is_set("onreply_route")) { t_on_reply("MANAGE_REPLY"); } } if (is_method("INVITE")) { if(!t_is_set("failure_route")) { t_on_failure("MANAGE_FAILURE"); } }
if (!t_relay()) { sl_reply_error(); }
exit; }
# Per SIP request initial checks route[REQINIT] { #!ifdef WITH_ANTIFLOOD # flood detection from same IP and traffic ban for a while # be sure you exclude checking trusted peers, such as pstn gateways # - local host excluded (e.g., loop to self) if(src_ip!=myself) { if($sht(ipban=>$si)!=$null) { # ip is already blocked xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); exit; } if (!pike_check_req()) { xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); $sht(ipban=>$si) = 1; exit; } } #!endif if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") { # silent drop for scanners - uncomment next line if want to reply # sl_send_reply("200", "OK"); exit; }
if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; }
if(is_method("OPTIONS") && uri==myself && $rU==$null) { sl_send_reply("200","Keepalive"); exit; }
if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } }
# Handle requests within SIP dialogs route[WITHINDLG] { xlog("L_ERR","Entering withindlgs"); if (!has_totag()) return;
# sequential request withing a dialog should # take the path determined by record-routing if (loose_route()) { xlog("L_ERR","loose route"); route(DLGURI); if (is_method("BYE")) { xlog("L_ERR","BYE recevied in loose route"); setflag(FLT_ACC); # do accounting ... setflag(FLT_ACCFAILED); # ... even if the transaction fails } else if ( is_method("ACK") ) { # ACK is forwarded statelessly route(NATMANAGE); } else if ( is_method("NOTIFY") ) { # Add Record-Route for in-dialog NOTIFY as per RFC 6665. xlog("L_ERR","*****************1 Adding rr"); record_route(); }
route(RELAY); exit; }
if (is_method("SUBSCRIBE") && uri == myself) { # in-dialog subscribe requests route(PRESENCE); exit; } if ( is_method("ACK") ) { if ( t_check_trans() ) { # no loose-route, but stateful ACK; # must be an ACK after a 487 # or e.g. 404 from upstream server route(RELAY); exit; } else { # ACK without matching transaction ... ignore and discard exit; } } sl_send_reply("404","Not here"); exit; }
# Handle SIP registrations route[REGISTRAR] { if (!is_method("REGISTER")) return;
if(isflagset(FLT_NATS)) { setbflag(FLB_NATB); #!ifdef WITH_NATSIPPING # do SIP NAT pinging setbflag(FLB_NATSIPPING); #!endif } if (!save("location")) { sl_reply_error(); } exit; }
# User location service route[LOCATION] {
#!ifdef WITH_SPEEDDIAL # search for short dialing - 2-digit extension if($rU=~"^[0-9][0-9]$") { if(sd_lookup("speed_dial")) { route(SIPOUT); } } #!endif
#!ifdef WITH_ALIASDB # search in DB-based aliases if(alias_db_lookup("dbaliases")) { route(SIPOUT); } #!endif
$avp(oexten) = $rU; if (!lookup("location")) { $var(rc) = $rc; route(TOVOICEMAIL); t_newtran(); switch ($var(rc)) { case -1: case -3: send_reply("404", "Not Found"); exit; case -2: send_reply("405", "Method Not Allowed"); exit; } }
if (is_method("INVITE")) { setflag(FLT_ACCMISSED); }
route(RELAY); exit; }
# Presence server processing route[PRESENCE] { if(!is_method("PUBLISH|SUBSCRIBE")) return;
if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { route(TOVOICEMAIL); # returns here if no voicemail server is configured sl_send_reply("404", "No voicemail service"); exit; }
#!ifdef WITH_PRESENCE if (!t_newtran()) { sl_reply_error(); exit; }
if(is_method("PUBLISH")) { handle_publish(); t_release(); } else if(is_method("SUBSCRIBE")) { handle_subscribe(); t_release(); } exit; #!endif
# if presence enabled, this part will not be executed if (is_method("PUBLISH") || $rU==$null) { sl_send_reply("404", "Not here"); exit; } return; }
# IP authorization and user authentication route[AUTH] { #!ifdef WITH_AUTH
#!ifdef WITH_IPAUTH if((!is_method("REGISTER")) && allow_source_address()) { # source IP allowed return; } #!endif
if (is_method("REGISTER") || from_uri==myself) { # authenticate requests if (!auth_check("$fd", "subscriber", "1")) { auth_challenge("$fd", "0"); exit; } # user authenticated - remove auth header if(!is_method("REGISTER|PUBLISH")) consume_credentials(); } # if caller is not local subscriber, then check if it calls # a local destination, otherwise deny, not an open relay here if (from_uri!=myself && uri!=myself) { sl_send_reply("403","Not relaying"); exit; }
#!endif return; }
# Caller NAT detection route[NATDETECT] { #!ifdef WITH_NAT force_rport(); if (nat_uac_test("19")) { if (is_method("REGISTER")) { fix_nated_register(); } else { if(is_first_hop()) { set_contact_alias(); } } setflag(FLT_NATS); } #!endif return; }
# RTPProxy control and signaling updates for NAT traversal route[NATMANAGE] { #!ifdef WITH_NAT if (is_request()) { if(has_totag()) { if(check_route_param("nat=yes")) { setbflag(FLB_NATB); } } } if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return;
if(nat_uac_test("8")) { if(ds_is_from_list()){ xdbg("__META rtpengine priv->pub"); rtpengine_manage("replace-session-connection replace-origin direction=priv direction=pub"); } else { xdbg("__META rtpengine pub->priv"); rtpengine_manage("replace-session-connection replace-origin direction=pub direction=priv"); } } else { if(ds_is_from_list()) { xdbg("__META rtpengine priv->pub"); rtpengine_manage("replace-session-connection replace-origin trust-address direction=priv direction=pub"); } else { xdbg("__META rtpengine pub->priv"); rtpengine_manage("replace-session-connection replace-origin trust-address direction=pub direction=priv"); } }
if (is_request()) { if (!has_totag()) { if(t_is_branch_route()) { add_rr_param(";nat=yes"); } } }
if (is_reply()) { if(isbflagset(FLB_NATB)) { if(is_first_hop()) set_contact_alias(); } xlog("L_ERR","20202020 in is_reply"); } #!endif return; }
# URI update for dialog requests route[DLGURI] { #!ifdef WITH_NAT if(!isdsturiset()) { handle_ruri_alias(); } #!endif return; }
# Routing to foreign domains route[SIPOUT] { if (uri==myself) return; append_hf("P-hint: outbound\r\n"); route(RELAY); exit; }
# PSTN GW routing route[PSTN] { #!ifdef WITH_PSTN # check if PSTN GW IP is defined if (strempty($sel(cfg_get.pstn.gw_ip))) { xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); return; }
# route to PSTN dialed numbers starting with '+' or '00' # (international format) # - update the condition to match your dialing rules for PSTN routing if(!($rU=~"^(+|00)[1-9][0-9]{3,20}$")) return;
# only local users allowed to call if(from_uri!=myself) { sl_send_reply("403", "Not Allowed"); exit; }
if (strempty($sel(cfg_get.pstn.gw_port))) { $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); } else { $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" + $sel(cfg_get.pstn.gw_port); }
route(RELAY); exit; #!endif
return; }
# XMLRPC routing #!ifdef WITH_XMLRPC route[XMLRPC] { # allow XMLRPC from localhost if ((method=="POST" || method=="GET") && (src_ip==127.0.0.1)) { # close connection only for xmlrpclib user agents (there is a bug in # xmlrpclib: it waits for EOF before interpreting the response). if ($hdr(User-Agent) =~ "xmlrpclib") set_reply_close(); set_reply_no_connect(); dispatch_rpc(); exit; } send_reply("403", "Forbidden"); exit; } #!endif
# Routing to voicemail server route[TOVOICEMAIL] { #!ifdef WITH_VOICEMAIL if(!is_method("INVITE|SUBSCRIBE")) return;
# check if VoiceMail server IP is defined if (strempty($sel(cfg_get.voicemail.srv_ip))) { xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); return; } if(is_method("INVITE")) { if($avp(oexten)==$null) return;
$ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) + ":" + $sel(cfg_get.voicemail.srv_port); } else { if($rU==$null) return;
$ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) + ":" + $sel(cfg_get.voicemail.srv_port); } route(RELAY); exit; #!endif
return; }
//convert phone number from international to internal //+972112223344 <-> 011222334 route[TRANSLATE_DST_OUT] { xinfo("__META TRANSLATE_DST_OUT"); xdbg("__META To: $hdr(To)"); xdbg("__META Regexp: NUM_TRANSLATE_OUT_RE");
if(subst_uri("/NUM_TRANSLATE_OUT_RE/0\2/")) xdbg("__META URI translated"); else xdbg("__META Not translating number in URI");
if(subst_hf("To", "/NUM_TRANSLATE_OUT_RE/0\2/", "a")) xdbg("__META To header translated"); else xdbg("__META Not translating number in to header"); }
//convert phone number from internal format to international //011222334 <-> +<972>112223344 route[TRANSLATE_SRC_IN] { $var(number)=$rU; if($(var(number){s.substr,1,4})=="+972") { $rU="0"+$(var(number){s.substr,5,0}); } } /////////////////////////////////////////////////////////////////////////////
# Manage outgoing branches branch_route[MANAGE_BRANCH] { xdbg("new branch [$T_branch_idx] to $ru\n"); route(NATMANAGE); }
# Manage incoming replies onreply_route[MANAGE_REPLY] { xdbg("incoming reply\n");
// fix_nated_contact(); xlog("L_ERR","2020202020202 Got reply $ct");
if(status=~"[12][0-9][0-9]") { route(NATMANAGE); }
if(is_method("INVITE") && is_present_hf("P-Asserted-Identity")) { remove_hf("P-Asserted-Identity"); } }
# Manage failure routing cases failure_route[MANAGE_FAILURE] { xlog("Failure! Going to failure route."); route(NATMANAGE); if (t_is_canceled()) exit;
#!ifdef WITH_BLOCK3XX # block call redirect based on 3xx replies. if (t_check_status("3[0-9][0-9]")) { t_reply("404","Not found"); exit; } #!endif
#!ifdef WITH_BLOCK401407 # block call redirect based on 401, 407 replies. if (t_check_status("401|407")) { t_reply("404","Not found"); exit; } #!endif
#!ifdef WITH_VOICEMAIL # serial forking # - route to voicemail on busy or no answer (timeout) if (t_check_status("486|408")) { $du = $null; route(TOVOICEMAIL); exit; } #!endif }
event_route[topoh:msg-outgoing] { if($sndto(ip)=="freeswitch") { drop; } if($sndto(ip)=="81.24.193.248") { drop; } }
Edward
*From:* Daniel-Constantin Mierla miconda@gmail.com *Sent:* Tuesday, August 4, 2020 11:19 AM *To:* Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org; Edward Romanenco edward@telemessage.com *Subject:* Re: [SR-Users] Manipulating SDP IP for Inbound Calls
Hello,
the mangler module does not have any idea of inbound/outbound directions, so you can use it for any of them.
Also, the nathelper module should have a function allowing to change the ip in the sdp, iirc.
On the other hand, if you use rtppengine for the calls, then the ips should be replaced by it.
Do not forget to use msg_apply_changes() in case you want those changes to be visible immediately in the configuration file.
Cheers, Daniel
On 29.07.20 13:18, Edward Romanenco wrote:
Hey guys,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system.
Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.
For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?
v=0. o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 45878 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16
Edward
Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org mailto:sr-users@lists.kamailio.org https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
-- Daniel-Constantin Mierla -- www.asipto.com http://www.asipto.com www.twitter.com/miconda http://www.twitter.com/miconda -- www.linkedin.com/in/miconda http://www.linkedin.com/in/miconda Funding: https://www.paypal.me/dcmierla
I moved in to an ONREPLAY route and it seems to be working well with the mangler.
Thank you all.
Edward ________________________________ From: Daniel-Constantin Mierla miconda@gmail.com Sent: Tuesday, August 4, 2020 12:05 PM To: Edward Romanenco edward@telemessage.com; Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org Subject: Re: [SR-Users] Manipulating SDP IP for Inbound Calls
Hello,
hard to track the execution path without a test environment ... I would suggest to load debugger module and enable cfgtrace for it to see what actions in configuration file are executed, to be sure it gets to the fix_nated_sdp().
Cheers, Daniel
On 04.08.20 10:44, Edward Romanenco wrote: I tried using nathelper in the following way - fix_nated_sdp("2","XX.XX.XX.XX"); - it still shows my internal IP. Attaching my request routes, can you kindly check and see if I am using it correctly?
SDP . v=0. o=FreeSWITCH 1596486133 1596486134 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 43954 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16. a=ptime:20.
REQUEST ROUTES request_route { setflag(22); route(REQINIT);
if (is_method("CANCEL")) { if (t_check_trans()) { route(RELAY); } exit; }
route(WITHINDLG);
if(t_precheck_trans()) { t_check_trans(); exit; } t_check_trans();
remove_hf("Route"); if (is_method("INVITE|SUBSCRIBE")){// && is_present_hf("X-SESSION-ID")){ record_route(); } if (is_method("INVITE")) { setflag(FLT_ACC); }
if ($rU==$null) { sl_send_reply("484","Address Incomplete"); exit; }
route(OUTGOING); route(PSTN); route(INCOMING); route(RELAY); }
route[REMOVE_X_HEADERS] { if(is_present_hf("X-SESSION-ID")) { remove_hf("X-FS-Support"); remove_hf("X-Src"); remove_hf("X-DESTINATIONS"); remove_hf("X-SESSION-ID"); } xinfo("Remove X Headers; Contact Header is $ct"); }
route[INCOMING] { if(is_present_hf("X-SESSION-ID")) { return; }
if(ds_is_from_list("4")) { route(TRANSLATE_SRC_IN); }
route(REQUEST_PERMISSIONS); fix_nated_sdp("2","XX.XX.XX.XX"); exit; }
route[REQUEST_PERMISSIONS] { $var(body) = 0; $var(from) = $fU;
if($(var(from){s.substr,1,4})=="0972") { $var(from)=$(var(from){s.substr,2,0}); $fU = $var(from); }
jansson_set("string", "from", "$var(from)", "$var(body)");
if(is_present_hf("Diversion")) { xlog("L_INFO", "Call has been forwarded."); jansson_set("string","to","$oU","$var(body)"); } else { jansson_set("string","to","$tU","$var(body)"); }
jansson_set("string","forcepstn","false","$var(body)"); jansson_set("string", "source", "EGRESS", "$var(body)"); $http_req(all) = $null; $http_req(method) = "POST"; $http_req(hdr) = "Content-Type: application/json"; $http_req(hdr) = "Accept: application/json"; $http_req(hdr) = "Connection: keep-alive"; $http_req(body) = $var(body); $var(re_url)= "https://VNVHOST/voiceandvideo/makeCall"https://VNVHOST/voiceandvideo/makeCall; t_newtran();
if (http_async_query("$var(re_url)", "REQUEST_PERMISSIONS_REPLY") < 0) { t_reply("500", "Server Internal Error"); exit; } }
route[REQUEST_PERMISSIONS_REPLY] { if ($(http_err{s.len})) { xlog("L_ERR","Got error from server 1"); t_reply("500", "Server Internal Error"); exit; } else if ($http_rs != 200) { xlog("L_ERR","Got error from server 2"); t_reply("500", "Server Error"); exit; }
# Populate dialog variables for CDR Creation $var(count) = 0; jansson_get("list",$http_rb,"$dlg_var(destinations_array)"); jansson_get("msgID", $http_rb, "$dlg_var(session_id)"); jansson_get("resultCode",$http_rb,"$dlg_var(resultCode)");
if($dlg_var(resultCode)!=0) { t_reply("500","Server Internal Error"); exit; }
## EGRESS Server Information route(ADD_TELEMESSAGE_HDRS); $var(setid) = "1";
if(!ds_select_dst("1", "4")) { send_reply("404", "No destination"); exit; }
route(RELAY); exit; }
route[RELAY] { if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { if(!t_is_set("branch_route")) { t_on_branch("MANAGE_BRANCH"); } }
if (is_method("INVITE|SUBSCRIBE|UPDATE")) { if(!t_is_set("onreply_route")) { t_on_reply("MANAGE_REPLY"); } } if (is_method("INVITE")) { if(!t_is_set("failure_route")) { t_on_failure("MANAGE_FAILURE"); } }
if (!t_relay()) { sl_reply_error(); }
exit; }
# Per SIP request initial checks route[REQINIT] { #!ifdef WITH_ANTIFLOOD # flood detection from same IP and traffic ban for a while # be sure you exclude checking trusted peers, such as pstn gateways # - local host excluded (e.g., loop to self) if(src_ip!=myself) { if($sht(ipban=>$si)!=$null) { # ip is already blocked xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); exit; } if (!pike_check_req()) { xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); $sht(ipban=>$si) = 1; exit; } } #!endif if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") { # silent drop for scanners - uncomment next line if want to reply # sl_send_reply("200", "OK"); exit; }
if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; }
if(is_method("OPTIONS") && uri==myself && $rU==$null) { sl_send_reply("200","Keepalive"); exit; }
if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } }
# Handle requests within SIP dialogs route[WITHINDLG] { xlog("L_ERR","Entering withindlgs"); if (!has_totag()) return;
# sequential request withing a dialog should # take the path determined by record-routing if (loose_route()) { xlog("L_ERR","loose route"); route(DLGURI); if (is_method("BYE")) { xlog("L_ERR","BYE recevied in loose route"); setflag(FLT_ACC); # do accounting ... setflag(FLT_ACCFAILED); # ... even if the transaction fails } else if ( is_method("ACK") ) { # ACK is forwarded statelessly route(NATMANAGE); } else if ( is_method("NOTIFY") ) { # Add Record-Route for in-dialog NOTIFY as per RFC 6665. xlog("L_ERR","*****************1 Adding rr"); record_route(); }
route(RELAY); exit; }
if (is_method("SUBSCRIBE") && uri == myself) { # in-dialog subscribe requests route(PRESENCE); exit; } if ( is_method("ACK") ) { if ( t_check_trans() ) { # no loose-route, but stateful ACK; # must be an ACK after a 487 # or e.g. 404 from upstream server route(RELAY); exit; } else { # ACK without matching transaction ... ignore and discard exit; } } sl_send_reply("404","Not here"); exit; }
# Handle SIP registrations route[REGISTRAR] { if (!is_method("REGISTER")) return;
if(isflagset(FLT_NATS)) { setbflag(FLB_NATB); #!ifdef WITH_NATSIPPING # do SIP NAT pinging setbflag(FLB_NATSIPPING); #!endif } if (!save("location")) { sl_reply_error(); } exit; }
# User location service route[LOCATION] {
#!ifdef WITH_SPEEDDIAL # search for short dialing - 2-digit extension if($rU=~"^[0-9][0-9]$") { if(sd_lookup("speed_dial")) { route(SIPOUT); } } #!endif
#!ifdef WITH_ALIASDB # search in DB-based aliases if(alias_db_lookup("dbaliases")) { route(SIPOUT); } #!endif
$avp(oexten) = $rU; if (!lookup("location")) { $var(rc) = $rc; route(TOVOICEMAIL); t_newtran(); switch ($var(rc)) { case -1: case -3: send_reply("404", "Not Found"); exit; case -2: send_reply("405", "Method Not Allowed"); exit; } }
if (is_method("INVITE")) { setflag(FLT_ACCMISSED); }
route(RELAY); exit; }
# Presence server processing route[PRESENCE] { if(!is_method("PUBLISH|SUBSCRIBE")) return;
if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { route(TOVOICEMAIL); # returns here if no voicemail server is configured sl_send_reply("404", "No voicemail service"); exit; }
#!ifdef WITH_PRESENCE if (!t_newtran()) { sl_reply_error(); exit; }
if(is_method("PUBLISH")) { handle_publish(); t_release(); } else if(is_method("SUBSCRIBE")) { handle_subscribe(); t_release(); } exit; #!endif
# if presence enabled, this part will not be executed if (is_method("PUBLISH") || $rU==$null) { sl_send_reply("404", "Not here"); exit; } return; }
# IP authorization and user authentication route[AUTH] { #!ifdef WITH_AUTH
#!ifdef WITH_IPAUTH if((!is_method("REGISTER")) && allow_source_address()) { # source IP allowed return; } #!endif
if (is_method("REGISTER") || from_uri==myself) { # authenticate requests if (!auth_check("$fd", "subscriber", "1")) { auth_challenge("$fd", "0"); exit; } # user authenticated - remove auth header if(!is_method("REGISTER|PUBLISH")) consume_credentials(); } # if caller is not local subscriber, then check if it calls # a local destination, otherwise deny, not an open relay here if (from_uri!=myself && uri!=myself) { sl_send_reply("403","Not relaying"); exit; }
#!endif return; }
# Caller NAT detection route[NATDETECT] { #!ifdef WITH_NAT force_rport(); if (nat_uac_test("19")) { if (is_method("REGISTER")) { fix_nated_register(); } else { if(is_first_hop()) { set_contact_alias(); } } setflag(FLT_NATS); } #!endif return; }
# RTPProxy control and signaling updates for NAT traversal route[NATMANAGE] { #!ifdef WITH_NAT if (is_request()) { if(has_totag()) { if(check_route_param("nat=yes")) { setbflag(FLB_NATB); } } } if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return;
if(nat_uac_test("8")) { if(ds_is_from_list()){ xdbg("__META rtpengine priv->pub"); rtpengine_manage("replace-session-connection replace-origin direction=priv direction=pub"); } else { xdbg("__META rtpengine pub->priv"); rtpengine_manage("replace-session-connection replace-origin direction=pub direction=priv"); } } else { if(ds_is_from_list()) { xdbg("__META rtpengine priv->pub"); rtpengine_manage("replace-session-connection replace-origin trust-address direction=priv direction=pub"); } else { xdbg("__META rtpengine pub->priv"); rtpengine_manage("replace-session-connection replace-origin trust-address direction=pub direction=priv"); } }
if (is_request()) { if (!has_totag()) { if(t_is_branch_route()) { add_rr_param(";nat=yes"); } } }
if (is_reply()) { if(isbflagset(FLB_NATB)) { if(is_first_hop()) set_contact_alias(); } xlog("L_ERR","20202020 in is_reply"); } #!endif return; }
# URI update for dialog requests route[DLGURI] { #!ifdef WITH_NAT if(!isdsturiset()) { handle_ruri_alias(); } #!endif return; }
# Routing to foreign domains route[SIPOUT] { if (uri==myself) return; append_hf("P-hint: outbound\r\n"); route(RELAY); exit; }
# PSTN GW routing route[PSTN] { #!ifdef WITH_PSTN # check if PSTN GW IP is defined if (strempty($sel(cfg_get.pstn.gw_ip))) { xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); return; }
# route to PSTN dialed numbers starting with '+' or '00' # (international format) # - update the condition to match your dialing rules for PSTN routing if(!($rU=~"^(+|00)[1-9][0-9]{3,20}$")) return;
# only local users allowed to call if(from_uri!=myself) { sl_send_reply("403", "Not Allowed"); exit; }
if (strempty($sel(cfg_get.pstn.gw_port))) { $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); } else { $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" + $sel(cfg_get.pstn.gw_port); }
route(RELAY); exit; #!endif
return; }
# XMLRPC routing #!ifdef WITH_XMLRPC route[XMLRPC] { # allow XMLRPC from localhost if ((method=="POST" || method=="GET") && (src_ip==127.0.0.1)) { # close connection only for xmlrpclib user agents (there is a bug in # xmlrpclib: it waits for EOF before interpreting the response). if ($hdr(User-Agent) =~ "xmlrpclib") set_reply_close(); set_reply_no_connect(); dispatch_rpc(); exit; } send_reply("403", "Forbidden"); exit; } #!endif
# Routing to voicemail server route[TOVOICEMAIL] { #!ifdef WITH_VOICEMAIL if(!is_method("INVITE|SUBSCRIBE")) return;
# check if VoiceMail server IP is defined if (strempty($sel(cfg_get.voicemail.srv_ip))) { xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); return; } if(is_method("INVITE")) { if($avp(oexten)==$null) return;
$ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) + ":" + $sel(cfg_get.voicemail.srv_port); } else { if($rU==$null) return;
$ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) + ":" + $sel(cfg_get.voicemail.srv_port); } route(RELAY); exit; #!endif
return; }
//convert phone number from international to internal //+972112223344 <-> 011222334 route[TRANSLATE_DST_OUT] { xinfo("__META TRANSLATE_DST_OUT"); xdbg("__META To: $hdr(To)"); xdbg("__META Regexp: NUM_TRANSLATE_OUT_RE");
if(subst_uri("/NUM_TRANSLATE_OUT_RE/0\2/")) xdbg("__META URI translated"); else xdbg("__META Not translating number in URI");
if(subst_hf("To", "/NUM_TRANSLATE_OUT_RE/0\2/", "a")) xdbg("__META To header translated"); else xdbg("__META Not translating number in to header"); }
//convert phone number from internal format to international //011222334 <-> +<972>112223344 route[TRANSLATE_SRC_IN] { $var(number)=$rU; if($(var(number){s.substr,1,4})=="+972") { $rU="0"+$(var(number){s.substr,5,0}); } } /////////////////////////////////////////////////////////////////////////////
# Manage outgoing branches branch_route[MANAGE_BRANCH] { xdbg("new branch [$T_branch_idx] to $ru\n"); route(NATMANAGE); }
# Manage incoming replies onreply_route[MANAGE_REPLY] { xdbg("incoming reply\n");
// fix_nated_contact(); xlog("L_ERR","2020202020202 Got reply $ct");
if(status=~"[12][0-9][0-9]") { route(NATMANAGE); }
if(is_method("INVITE") && is_present_hf("P-Asserted-Identity")) { remove_hf("P-Asserted-Identity"); } }
# Manage failure routing cases failure_route[MANAGE_FAILURE] { xlog("Failure! Going to failure route."); route(NATMANAGE); if (t_is_canceled()) exit;
#!ifdef WITH_BLOCK3XX # block call redirect based on 3xx replies. if (t_check_status("3[0-9][0-9]")) { t_reply("404","Not found"); exit; } #!endif
#!ifdef WITH_BLOCK401407 # block call redirect based on 401, 407 replies. if (t_check_status("401|407")) { t_reply("404","Not found"); exit; } #!endif
#!ifdef WITH_VOICEMAIL # serial forking # - route to voicemail on busy or no answer (timeout) if (t_check_status("486|408")) { $du = $null; route(TOVOICEMAIL); exit; } #!endif }
event_route[topoh:msg-outgoing] { if($sndto(ip)=="freeswitch") { drop; } if($sndto(ip)=="81.24.193.248") { drop; } }
Edward ________________________________ From: Daniel-Constantin Mierla miconda@gmail.commailto:miconda@gmail.com Sent: Tuesday, August 4, 2020 11:19 AM To: Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org; Edward Romanenco edward@telemessage.commailto:edward@telemessage.com Subject: Re: [SR-Users] Manipulating SDP IP for Inbound Calls
Hello,
the mangler module does not have any idea of inbound/outbound directions, so you can use it for any of them.
Also, the nathelper module should have a function allowing to change the ip in the sdp, iirc.
On the other hand, if you use rtppengine for the calls, then the ips should be replaced by it.
Do not forget to use msg_apply_changes() in case you want those changes to be visible immediately in the configuration file.
Cheers, Daniel
On 29.07.20 13:18, Edward Romanenco wrote: Hey guys,
I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system.
Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.
For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?
v=0. o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40. s=FreeSWITCH. c=IN IP4 172.18.0.40. t=0 0. m=audio 45878 RTP/AVP 8 101. a=rtpmap:8 PCMA/8000. a=rtpmap:101 telephone-event/8000. a=fmtp:101 0-16
Edward
_______________________________________________ Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
-- Daniel-Constantin Mierla -- www.asipto.comhttp://www.asipto.com www.twitter.com/micondahttp://www.twitter.com/miconda -- www.linkedin.com/in/micondahttp://www.linkedin.com/in/miconda Funding: https://www.paypal.me/dcmierla
-- Daniel-Constantin Mierla -- www.asipto.comhttp://www.asipto.com www.twitter.com/micondahttp://www.twitter.com/miconda -- www.linkedin.com/in/micondahttp://www.linkedin.com/in/miconda Funding: https://www.paypal.me/dcmierla