RADIUS का उपयोग करके FreeSWITCH पर एक वीओआईपी कार्ड प्लेटफॉर्म को लागू करना

कार्य रैक में पुरानी बकवास से छुटकारा पाने और एक विशेष रूप से एक्सेस नंबर पर कॉल करके और एक पिन कोड दर्ज करके अन्य ऑपरेटरों के ग्राहकों के लिए एक लंबी दूरी / अंतर्राष्ट्रीय संचार प्रदान करने के लिए, थोड़ा भूले हुए, लेकिन अभी भी मौजूदा तकनीक के एक सॉफ्टवेयर संस्करण को लागू करना था। सब्सक्राइबर प्राधिकरण RADIUS के माध्यम से बिलिंग से गुजरता है, और कॉल रिकॉर्ड वहां जोड़े जाते हैं।

प्लेटफ़ॉर्म स्वयं किसी के लिए बहुत कम रुचि रखता है, लेकिन जब मैंने कॉन्फिग्स लिखा, तो मुझे वास्तव में उपयोग के उदाहरणों की कमी थी, मुझे उम्मीद है कि यह उदाहरण किसी के लिए उपयोगी है।

मेरा काम केवल टेलीफ़ोनी के साथ सतही रूप से जुड़ा हुआ है, इसलिए मैं एस्टरिस्क से बहुत परिचित नहीं हूं, इसलिए, बेस प्लेटफॉर्म चुनते समय, मेरे पास कोई प्रतिबंध और पूर्वाग्रह नहीं थे। एस्टरिस्क पर सब कुछ लागू करना तर्कसंगत होगा, विशेष रूप से कंपनी में इसके सक्रिय उपयोग को देखते हुए, लेकिन कड़वे अनुभव के अनुसार, इसका गिरना सबसे अधिक आवेग क्षण में होता है और सेवा का एक सरल पुनरारंभ मदद नहीं करता है। इसलिए, सकारात्मक समीक्षाओं और समीक्षाओं को पढ़ने के बाद, प्लेटफ़ॉर्म को FreeSWITCH चुना गया। बेशक, इसके लिए प्रलेखन रूसी में बहुत छोटा है और यहां तक ​​कि कम है, लेकिन यह डरा नहीं है, क्योंकि मुझे अच्छी तरह से याद है कि सूर्यास्त h323 पर तारांकन कई संकुल से इकट्ठा किया गया था, संस्करणों के सख्त संस्करणों में और केवल कुछ ही उदाहरणों के अनुसार। सेटअप प्रक्रिया से पहले और उसके दौरान, विकी का सावधानीपूर्वक अध्ययन किया गया था।

समस्या का बयान


ऐसे कई लोग हैं, जो विशेष रूप से एक मोबाइल ऑपरेटर के टैरिफ की तुलना में लंबी दूरी की कॉल करना चाहते हैं, फोन पर या बिना किसी काम के नंबर से, जहां "8-कू" तक कोई पहुंच नहीं है। ऐसा करने के लिए, एक एक्सेस नंबर (या कई) का आयोजन किया जाता है, जहां ग्राहक कॉल करता है (बाद में 555555), प्राधिकरण को पास करता है (कॉलर आईडी या पिन कोड द्वारा), धन के अपने वर्तमान संतुलन को सुनता है और उस नंबर को डायल करता है जिसे वह कॉल करना चाहता था, कॉल के बारे में डेटा बिलिंग के लिए बिलिंग में जाना चाहिए। वास्तव में, यह सब पहले से ही प्राचीन वर्षों से काम कर रहा है (और एक विशाल लोकप्रिय सेवा थी) विशाल और डरावना सिस्को AS5300 पर। कॉलर आईडी द्वारा प्राधिकरण की आलोचना को स्वीकार करते हुए: किसी के पास प्रीपेड सिस्टम नहीं है और बड़ी शेष राशि है - जोखिम कम से कम हैं, कुछ ग्राहक हैं - यह अनुमान लगाना मुश्किल है कि कौन सी कॉलर आईडी मुफ्त में कॉल कर सकती है, वीओआईपी के माध्यम से कॉल कर सकती है और नंबर बदल सकती है - बेकार है ऐसी कॉल से लाभ न्यूनतम है, स्थानीय ऑपरेटरों को ट्रैक करना आसान है।

सेवा आरेख की तरह कुछ, दाईं ओर की संख्याएं एक्सटेंशन के लिए अभिव्यक्ति हैं:



कुछ भी जटिल नहीं है, लेकिन मुझे टिंकर करना पड़ा।
  1. Xml में कॉन्फ़िगरेशन का प्रारूप, जो व्यवस्थापक से बिल्कुल परिचित नहीं है, इसके अलावा, पहली बार में उनके समावेशन का तर्क बहुत भ्रमित करने वाला लगता है।
  2. स्थिति की स्थितियों का बहुत ही असामान्य तर्क, विशेष रूप से, मैं हमेशा ब्रेक = "ऑन-ट्रू" (मैं सच में कार्यक्रम के निष्पादन को कैसे बाधित कर सकता हूं) से चकित था, मैं आपको सलाह देता हूं कि इस मुद्दे का सावधानीपूर्वक अध्ययन करें और सब कुछ बहुत तार्किक हो जाता है। संक्षेप में, ब्रेक केवल शिकार प्रक्रिया को प्रभावित करता है (बाद में शिकार करने के बारे में) और वर्तमान एक्सटेंशन में शर्तों के प्रसंस्करण को बाधित करता है यदि स्थिति मैच (सच), मेल नहीं खाती (डिफ़ॉल्ट रूप से झूठी) या बिल्कुल भी बाधित नहीं होती है और किसी भी मामले में अगली स्थिति को संसाधित करती है (कभी नहीं )।
  3. सभी गणनाएँ, आदिम लोगों को छोड़कर, जिनके लिए आप इनलाइन = "सही" सेट कर सकते हैं, केवल स्थानांतरण या निष्पादन-अनुकूलन के बाद किए जाते हैं। लब्बोलुआब यह है कि एफएस XML_Dialplan को दो चरणों में संसाधित करता है - शिकार और निष्पादन (शिकार और निष्पादन)। शिकार के दौरान, स्थितियों, कार्यों और विरोधी कार्यों का प्रदर्शन किया जाता है और निष्पादित होने वाले अनुप्रयोगों का चयन किया जाता है। इसलिए, जब आपको किसी जटिल एप्लिकेशन के परिणाम प्राप्त करने की आवश्यकता होती है, तो आपको दूसरे एक्सटेंशन पर जाने की आवश्यकता होती है।
  4. आप कुछ भी नहीं ले सकते हैं और कुछ को नियमित अभिव्यक्तियों के बिना एक स्ट्रिंग में बदल सकते हैं और यह केवल प्राथमिक बीजीय कार्यों की कमी के लिए बहुत भ्रामक है।
  5. प्रलेखन, विशेष रूप से मॉड्यूल के लिए, बहुत दुर्लभ है (अप्रैल में तय किए गए फ़ंक्शन का एक महाकाव्य विवरण था: यदि आपको नहीं पता कि यह ऐप क्या करता है तो आपको इसका उपयोग नहीं करना चाहिए! :))।


निर्णय


मैं एफएस की स्थापना का वर्णन नहीं करूंगा, वहां सब कुछ सरल है, मानक के अलावा, इसके अलावा आपको केवल लापता मॉड्यूल को संकलित करने की आवश्यकता है। सभी पथ उस फ़ोल्डर के सापेक्ष इंगित किए जाएंगे जहां एफएस स्थापित है।

कॉन्फ़िगरेशन के लिए, एक अलग संख्या आवंटित की गई थी और एफएस को भेज दी गई थी (बाहरी सर्वर से कॉल करने पर एक गैर-मानक पोर्ट का उपयोग करने की एक विशेषता है - 1280)। हम गोपनीय / sip_profiles / बाहरी / sipgate.xml नामक sipgate (IP पता 10.10.10.10) नामक सर्वर के माध्यम से आउटगोइंग कॉल (सार्वजनिक संदर्भ में सही एक्सटेंशन प्राप्त करने के लिए) बनाते हैं, मेरे मामले में यह प्राधिकरण के बिना पर्याप्त है:

<include> <gateway name="sipgate"> <param name="username" value="<  >"/> <param name="proxy" value="10.10.10.10"/> <param name="register" value="false"/> <param name="caller-id-in-from" value="true"/> </gateway> </include> 


आगे के काम के लिए, एफएस को रोकना आवश्यक है और फ़ोल्डर लगता है / ru / RU / elena वांछित बिट दर की ध्वनि फ़ाइलों से भरा था, मेरे मामले में 8000 ( फाइलों के साथ संग्रह )। Freeswitch.xml में, एन को आरयू में बदलें:

 <section name="languages" description="Language Management"> <!-- <X-PRE-PROCESS cmd="include" data="lang/en/*.xml"/>--> <X-PRE-PROCESS cmd="include" data="lang/ru/*.xml"/> </section> 


वॉइस फ़ाइलों का उपयोग मानक और पर्याप्त नहीं था, लेकिन रिकॉर्डिंग अभी भी एक समस्या है।
डायलप्लान / public.xml कॉन्फिग को अधिकतम ट्रिम कर दिया गया है:

 <include> <context name="public"> <extension name="unloop"> <condition field="${unroll_loops}" expression="^true$"/> <condition field="${sip_looped_call}" expression="^true$"> <action application="deflect" data="${destination_number}"/> </condition> </extension> <X-PRE-PROCESS cmd="include" data="public/*.xml"/> </context> </include> 


और फ़ाइल conf / dialplan / public / voip_public.xml में हम इनकमिंग कॉल के लिए एक्सटेंशन लिखते हैं, जहां हम तुरंत इसे संख्या द्वारा अधिकृत करने का प्रयास करते हैं:

 <include> <extension name="voip_platform_pub_step1"> <condition field="destination_number" expression="^(555555)$"> <!--          --> <action application="log" data="INFO pub/1 RAD_AUTH STEP1"/> <action application="set" data="process_cdr=b_only"/><!--   Stop accounting    , ..      ,    Start  -    ... --> <action inline="true" application="set" data="pin_auth_count=0"/><!--     ,        -   --> <!--     radius  --> <action inline="true" application="set" data="CALLID=${uuid}"/> <action inline="true" application="set" data="CALLINGNUMBER=${caller_id_number}"/> <action inline="true" application="set" data="USERNAME=${caller_id_number}"/> <action inline="true" application="set" data="STEP=fs1"/><!--      (     ) --> <action application="auth_function" data="in ${CALLEDNUMBER}, in ${USERNAME}, in ${PASSWD}, out AUTH_RESULT"/><!--    radius,    ../../autoload_configs/rad_auth.conf.xml --> <action application="log" data="INFO pub/1 AUTH_RESULT=${AUTH_RESULT}: credit_amount=${credit_amount}; return_code=${return_code}"/> <action application="set" data="domain_name=$${domain}"/> <action application="transfer" data="10 XML voip"/><!--         --> </condition> </extension> </include> 


"STEP = fs1" पर अलग ध्यान दें - मेरे मामले में बिलिंग को यह बताने में अधिक सुविधाजनक था कि फ्लैग fs1 के साथ कॉलर आईडी द्वारा प्राधिकरण, और पिन fs1pin द्वारा प्राधिकरण।

टिप्पणियों में conf / autoload_configs / rad_auth.conf.xml (RADIUS सर्वर 10.20.20.20 का आईपी पता) का उल्लेख है:

 <configuration name="rad_auth.conf" description="radius authentification module"> <settings> </settings> <client> <param name="authserver" value="10.20.20.20:1812:radiussecret"/> <param name="dictionary" value="/usr/local/etc/radiusclient/dictionary.all"/> <param name="seqfile" value="/var/run/radius.seq"/> <param name="mapfile" value="/usr/local/etc/radiusclient/port-id-map"/> <param name="default_realm" value=""/> <param name="radius_timeout" value="3"/> <param name="radius_retries" value="2"/> <param name="radius_deadtime" value="0"/> <param name="bindaddr" value="*"/> </client> <vsas> <!--name= , id=   dictionary, value=    , pec=  dictionary, expr=       , direction=  --> <param name="Acct-Session-Id" id="44" value="CALLID" pec="0" expr="1" direction="in"/> <param name="Freeswitch-Ani" id="8" value="CALLINGNUMBER" pec="27880" expr="1" direction="in"/> <param name="Freeswitch-Dst" id="5" value="CALLEDNUMBER" pec="27880" expr="1" direction="in"/> <param name="NAS-Port-Type" id="61" value="0" pec="0" expr="0" direction="in"/> <param name="Connect-Info" id="77" value="STEP" pec="0" expr="1" direction="in"/> <param name="CREDIT_AMOUNT" id="101" value="credit_amount" pec="9" expr="0" direction="out"/> <param name="CREDIT_TIME" id="102" value="credit_time" pec="9" expr="0" direction="out"/> <param name="RADIUS_RETURN_CODE" id="103" value="return_code" pec="9" expr="0" direction="out"/> </vsas> </configuration> 


और अब सभी मुख्य तर्क conf / dialplan / voip.xml फ़ाइल में, लेख की शुरुआत में योजना के अनुसार:

 <?xml version="1.0" encoding="utf-8"?> <include> <context name="voip"> <extension name="unloop"> <condition field="${unroll_loops}" expression="^true$"/> <condition field="${sip_looped_call}" expression="^true$"> <action application="deflect" data="${destination_number}"/> </condition> </extension> <extension name="voip_10"> <condition field="destination_number" expression="^10$" break="on-false"/> <condition field="${AUTH_RESULT}" expression="^OK$" break="on-true"> <!--   IVR   dtmf  --> <action application="log" data="INFO voip_10 AUTH_RESULT=${AUTH_RESULT} => Read DTMF"/> <action application="answer"/> <action application="sleep" data="1000"/> <action application="play_and_get_digits" data="6 20 5 30000 # phrase:voip_get_digits voicemail/vm-fail_auth.wav digits ^\**(\d{6}|\d{10,20})\**$ 5000"/><!-- <min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> <digit_timeout> --> <action application="transfer" data="20 XML voip"/> </condition> <condition field="${return_code}" expression="^h323-return-code=6$" break="on-true"> <!--      =>      --> <action application="log" data="INFO voip_10 RETURN_CODE = 6 => Closed account"/> <action application="answer"/> <action application="sleep" data="1000"/> <!--TODO!!!      --> <action application="playback" data="voicemail/vm-not_available.wav"/> <action application="hangup" data="NORMAL_CLEARING"/> </condition> <!--TODO!!!     --> <condition field="${pin_auth_count}" expression="^0$" break="on-true"><!--        --> <!--         ,  PIN --> <action inline="true" application="set" data="pin_auth_count=1"/> <action application="log" data="INFO voip_10 RETURN_CODE = OTHER"/> <action application="answer"/> <action application="sleep" data="1000"/> <action application="play_and_get_digits" data="10 10 5 30000 # phrase:voip_get_pin conference/conf-bad-pin.wav pin ^(\d{10})$ 5000"/><!-- <min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> <digit_timeout> --> <action application="transfer" data="15 XML voip"/> </condition> <condition> <!--      ,        ,       PIN-,     PIN-     --> <action application="log" data="INFO voip_10 Prevent second PIN authentification"/> <action application="answer"/> <action application="sleep" data="1000"/> <!--TODO!!!         --> <action application="playback" data="voicemail/vm-not_available.wav"/> <action application="hangup" data="NORMAL_CLEARING"/> </condition> </extension> <extension name="voip_15"> <condition field="destination_number" expression="^15$"/> <condition field="${pin}" expression="^(\d{6})(\d{4})$"> <!--      PIN- --> <action application="log" data="INFO voip_15 pin=($1+$2) => RAD_AUTH STEP1/PIN"/> <action inline="true" application="set" data="CALLINGNUMBER=${caller_id_number}"/> <action inline="true" application="set" data="USERNAME=$1"/> <action inline="true" application="set" data="PASSWD=$2"/> <action inline="true" application="set" data="STEP=fs1pin"/> <action application="log" data="INFO voip_15 CALLID=${CALLID}; CALLINGNUMBER=${CALLINGNUMBER}; USERNAME=${USERNAME}"/> <action application="auth_function" data="in ${CALLEDNUMBER}, in ${USERNAME}, in ${PASSWD}, out AUTH_RESULT"/> <action application="log" data="INFO voip_15 AUTH_RESULT=${AUTH_RESULT}: credit_amount=${credit_amount}; return_code=${return_code}"/> <action application="transfer" data="10 XML voip"/><!--               --> </condition> </extension> <extension name="voip_20"> <condition field="destination_number" expression="^20$"/> <condition field="${digits}" expression="^\**(\d+)\**$"> <!--         --> <action inline="true" application="set" data="digits=$1"/> <action inline="true" application="set" data="digits=${regex(${digits}|^(\d{6})$|83532%1)}"/><!--  85555 –          ^(\d{6})$  ,      --> <action application="log" data="INFO voip_20 DTMF digits=${digits} => RAD_AUTH STEP2"/> <action application="log" data="INFO voip_20 CALLID=${CALLID}; CALLINGNUMBER=${CALLINGNUMBER}; USERNAME=${USERNAME}"/> <action inline="true" application="set" data="CALLEDNUMBER=${digits}"/> <!--       fs2pin  fs2 --> <action inline="true" application="set" data="STEP=${regex(${STEP}|^fs\d(.*)$|fs2%1)}"/> <action application="auth_function" data="in ${CALLEDNUMBER}, in ${USERNAME}, in ${PASSWD}, out AUTH_RESULT"/> <action application="log" data="INFO voip_20 AUTH_RESULT=${AUTH_RESULT}: credit_amount=${credit_amount}; credit_time=${credit_time}; return_code=${return_code}"/> <!--            --> <action application="export" data="nolocal:api_on_answer=sched_hangup +${credit_time} ${uuid} alloted_timeout" /> <action application="transfer" data="30 XML voip"/> </condition> </extension> <extension name="voip_30"> <condition field="destination_number" expression="^30$" break="on-false"/> <condition field="${AUTH_RESULT}" expression="^OK$" break="on-true"> <action application="log" data="INFO voip_30 AUTH_RESULT=${AUTH_RESULT} => Call number"/> <action inline="true" application="set" data="effective_caller_id_number=35555555555"/> <!--      (|)    (fs2|fs2pin),     Freeswitch-CLID   --> <action inline="true" application="set" data="effective_caller_id_name=${STEP}"/> <!--     USERNAME    ,   mod_radius_cdr        User-Name   --> <action application="export" data="nolocal:acc_username=${USERNAME}"/> <!-- <action application="set_profile_var" data="Caller-Username=${USERNAME}"/>         mod_radius_cdr,         --> <action application="set" data="hangup_after_bridge=true"/><!--  !     --> <action application="bridge" data="sofia/gateway/sipgate/${digits}"/> <!--TODO!!!    --> <action application="log" data="INFO voip_30 AFTER BRIDGE"/> </condition> <!--TODO!!!        ,    .. --> <!--TODO!!! h323-return-code=9 Access denied -     ,        --> <condition> <action application="log" data="INFO voip_30 RETURN_CODE = OTHER"/> <action application="answer"/> <action application="sleep" data="1000"/> <action application="playback" data="zrtp/zrtp-status_error.wav"/> <action application="hangup" data="NORMAL_CLEARING"/> </condition> </extension> </context> </include> 


उल्लेखित वाक्यांश: voip_get_digits और वाक्यांश: voip_get_pin - "वाक्यांश" जो कि इनपुट की प्रतीक्षा करते समय क्लाइंट को कहा जाएगा, और दूसरा इसके बिना किया जा सकता है। भंडारण में व्यस्त / lang / ru / viop.xml:

 <include> <macro name="voip_get_digits" pause="250"> <input pattern="(.*)"> <match> <action function="play-file" data="ivr/ivr-account_balance_is.wav"/> <action function="say" data="${credit_amount}" method="pronounced" type="currency"/> <action function="play-file" data="ivr/ivr-please_enter_the_phone_number.wav"/> </match> </input> </macro> <macro name="voip_get_pin" pause="250"> <input pattern="(.*)"> <match> <action function="play-file" data="ivr/ivr-please_enter_pin_followed_by_pound.wav"/> <action function="execute" data="sleep(1000)"/> </match> </input> </macro> </include> 


और भी conf / autoload_configs / mod_radius_cdr.conf.xml config, जहां व्यावहारिक रूप से कुछ भी कॉन्फ़िगर नहीं किया गया है और वास्तव में सभी तर्क कोड में हार्ड-कोडित हैं:

 <configuration name="mod_radius_cdr.conf" description="RADIUS CDR Configuration"> <settings> <param name="dictionary" value="/usr/local/etc/radiusclient/dictionary.all"/> <param name="seqfile" value="/var/run/radius.seq"/> <param name="acctserver" value="10.20.20.20:1813:radiussecret"/> <param name="radius_retries" value="2"/> <param name="radius_timeout" value="3"/> <param name="radius_deadtime" value="0"/> </settings> </configuration> 


मुझे इस मॉड्यूल के कोड को थोड़ा संशोधित करना था, क्योंकि आँकड़ों को या तो संख्या या लॉगिन से डंप किया जाना चाहिए, लेकिन मुझे यह नहीं पता था कि इस मॉड्यूल से कैसे गुजरना है, जो कि नियमित साधन का उपयोग करके प्राधिकरण के ध्वज के साथ किया जाता है।

नतीजतन, जब सब कुछ काम कर रहा था, तो अंतिम लॉग / freeswitch.xml.fsxml कॉन्फ़िगरेशन को कम करने के लिए सामान्य एफएस कॉन्फ़िगरेशन को गंभीर रूप से डाला गया था।
पाठ के अनुसार, गुलजार हैं, उनके बिना सब कुछ काम करता है, लेकिन अगर आप उन्हें बनाते हैं तो यह अधिक सुंदर होगा।

Source: https://habr.com/ru/post/In189148/


All Articles