From 40ef42ff3ac6d7df1bb191636ed38e391e851f31 Mon Sep 17 00:00:00 2001 From: Grzegorz Sluja <grzegorz.sluja@iopsys.eu> Date: Mon, 12 Dec 2022 13:36:40 +0000 Subject: [PATCH] Respond to requests only from the configured SIP proxy An incoming SIP request will be silently dropped if the following conditions are all met: - The request is about to create a new session - The source IP address of the request is not the address of the configured proxy Note - The source port of the request is not checked since we have not found the good way to retrieve the port that is used for transmission - If the configured proxy is a domain name other than IP address, the resolved IP address might be different from the one which is being used in existing sessions --- channels/chan_pjsip.c | 27 +++++++++++++++++++++++++++ include/asterisk/res_pjsip.h | 7 +++++++ res/res_pjsip/config_global.c | 19 +++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 674af7786d..782fba28c3 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -3157,6 +3157,33 @@ static int chan_pjsip_incoming_request(struct ast_sip_session *session, struct p SCOPE_EXIT_RTN_VALUE(0, "%s: No channel\n", ast_sip_session_get_name(session)); } + if (ast_sip_get_accept_proxy_req_only() && + session->inv_session->dlg && session->inv_session->dlg->state != PJSIP_DIALOG_STATE_ESTABLISHED) { + char buf[256]; + struct ast_sockaddr resolved_addr; + + pj_sockaddr_print(&rdata->pkt_info.src_addr, buf, sizeof(buf), 3); + ast_log(LOG_NOTICE, "Request received from address: <%s>\n", buf); + + resolved_addr.ss.ss_family = AST_AF_UNSPEC; + if (ast_get_ip(&resolved_addr, session->endpoint->fromdomain)) { + ast_log(LOG_ERROR, "Could not resolve the domain name: %s\n", session->endpoint->fromdomain); + } else { + pj_sockaddr proxy_addr; + + ast_sockaddr_to_pj_sockaddr(&resolved_addr, &proxy_addr); + pj_sockaddr_set_port(&proxy_addr, rdata->pkt_info.src_port); + + pj_sockaddr_print(&proxy_addr, buf, sizeof(buf), 3); + ast_log(LOG_NOTICE, "Outgoing proxy address: <%s>\n", buf); + + if (pj_sockaddr_cmp(&rdata->pkt_info.src_addr, &proxy_addr)) { + ast_sip_session_terminate(session, 400); + SCOPE_EXIT_RTN_VALUE(-1, "%s: Request not from Outgoing SIP proxy. Terminating session\n", ast_sip_session_get_name(session)); + } + } + } + /* Check for a to-tag to determine if this is a reinvite */ if (rdata->msg_info.to->tag.slen) { /* Weird case. We've received a reinvite but we don't have a channel. The most diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 72c3416bd2..758176dc8f 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -3089,6 +3089,13 @@ unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void); */ unsigned int ast_sip_get_use_callerid_contact(void); +/*! + * \brief Retrieve the global setting 'accept_proxy_req_only'. + * + * \retval value of accept_proxy_req_only + */ +unsigned int ast_sip_get_accept_proxy_req_only(void); + /*! * \brief Retrieve the global setting 'norefersub'. * diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c index 5bc1cc6704..ce2146a44d 100644 --- a/res/res_pjsip/config_global.c +++ b/res/res_pjsip/config_global.c @@ -50,6 +50,7 @@ #define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0 #define DEFAULT_IGNORE_URI_USER_OPTIONS 0 #define DEFAULT_USE_CALLERID_CONTACT 0 +#define DEFAULT_ACCEPT_PROXY_REQ_ONLY 0 #define DEFAULT_SEND_CONTACT_STATUS_ON_UPDATE_REGISTRATION 0 #define DEFAULT_TASKPROCESSOR_OVERLOAD_TRIGGER TASKPROCESSOR_OVERLOAD_TRIGGER_GLOBAL #define DEFAULT_NOREFERSUB 1 @@ -116,6 +117,7 @@ struct global_config { enum ast_sip_taskprocessor_overload_trigger overload_trigger; /*! Nonzero if norefersub is to be sent in Supported header */ unsigned int norefersub; + unsigned int accept_proxy_req_only; }; static void global_destructor(void *obj) @@ -474,6 +476,21 @@ unsigned int ast_sip_get_use_callerid_contact(void) return use_callerid_contact; } +unsigned int ast_sip_get_accept_proxy_req_only(void) +{ + unsigned int accept_proxy_req_only; + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return DEFAULT_ACCEPT_PROXY_REQ_ONLY; + } + + accept_proxy_req_only = cfg->accept_proxy_req_only; + ao2_ref(cfg, -1); + return accept_proxy_req_only; +} + unsigned int ast_sip_get_send_contact_status_on_update_registration(void) { unsigned int send_contact_status_on_update_registration; @@ -723,6 +740,8 @@ int ast_sip_initialize_sorcery_global(void) ast_sorcery_object_field_register(sorcery, "global", "norefersub", DEFAULT_NOREFERSUB ? "yes" : "no", OPT_YESNO_T, 1, FLDSET(struct global_config, norefersub)); + ast_sorcery_object_field_register(sorcery, "global", "accept_proxy_req_only", + DEFAULT_ACCEPT_PROXY_REQ_ONLY, OPT_UINT_T, 0, FLDSET(struct global_config, accept_proxy_req_only)); if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) { return -1; -- GitLab