Menu

Home

Python portable Protocol Simulator
- fully supported protocols): RADIUS, DIAMETER
- partially supported (python2 code only): DHCP, LDAP, DNS
- tested with python 2/3
- client examples included
- py2 code uses simplified dictionary.
- py3 code uses wireshark dictionary
- EAP: calculate keys (SIM, AKA, AKA')
- EAP: calculate hmac1, hmac256
- EAP: encode/decode AT_ENCR_DATA to get Pseudonym/Re-auth Identity
- EAP: HSS simulator
- RADIUS: encrypt/decrypt password
- tested on Linux (ARM and x86, x86-64), Solaris 10-x86 and Windows

Project Admins:


Discussion

  • L.Belov

    L.Belov - 2014-02-25

    Creating simple PCRF simulator supporting Gx functionality based on Pyprotosim software

    Thanks to Pyprotosim simulator , Python diameter library and provided examples, it is really possible to create your own PCRF simulator on your Windows or Linux machine for tests or study.

    This indeed can be useful for testers who want to check Gx functionality, and also for everyone who wants to study PCRF's Gx protocol on practice.

    Python 2.7, python-ldap module , PCRF simulator and LDAP server and PCEF client can all be installed on the same Windows or Linux machines (tested with RedHat 6.2 and Windows XP).

    What this small PCRF simulator can basically do? :)

    1) It accepts connections from PCEF client, check CCR-I(U) messages, query LDAP server with msisdn as a filter, checks user profile and sends reply back to PCEF with enforced policy charging rules. It also updates sessionid from CCR-I(U) and store it into LDAP subscriber profile - this is needed further to create push RAR-T(U) requests to PCEF via script.

    You configure PCC rules manually in LDAP's user's profile or using provisioning scripts.

    2) When session is established from PCEF, it is also possible to send push RAR messages from PCRF to PCEF using scripts.

    The PCRF simulator server complies with 3GPP TS 29.212 and supports CER,DWR,DPR,CCR-I,CCR-U,CCR-T,RAR-U,RAR-T messages. It listens 3868 and 3869 ports (which can be changed by user in the PCRF simulator server python file).

    It is assumed that PCEF knows already ip address of the user’s identity (identity is msisdn or imsi), for the case when IP-CAN session is being established. Within initial CCR-I request PCEF will provide msisdn and imsi to PCRF simulator, and msisdn from CCR request will be used as a filter for ldap query to subscriber database (ldap) and will return user profile entries, like PCC rules.

    However, if the user's identity is not known and PCEF sends CCR-I request with Framed-IP-Address ( IP of the UE) only, the PCRF simulator code can also be modified (ldap search filter only) without re-building LDAP schema.

    • If there is no LDAP server connectivity, for CCR-I(U) it sends DIAMETER AVP result-code 5003 ( Not authorized) to PCEF
    • If user's identity was not found in LDAP DB , it sends DIAMETER AVP result-code 5003 ( Not authorized) to PCEF
    • For any CCR-T requests it just simply sends CCA-T Diameter result code AVP 2001 Success
    • For any Watchdog DWR and Disconnect-Peer or Capabilities Exchange requests (CER) it simply sends corresponding Diameter result code AVP 2001 Success
    • For sending push RAR messages, PCRF simulator is listening command port 3869 and will send our messages to the connected PCEF client with scripts test_push_RAR-T(U).py

    For LDAP connectivity, OpenLDAP is used to create /modify user's profile. You can install OpenLDAP for Windows or for Linux, use some ldap browser software to modify PCC rules for users

     
  • Sergej Srepfler

    Sergej Srepfler - 2014-03-01

    One note about receiving TCP traffic (when you have multiple messages or high load)

    In my examples data stream is read in chunks (predefined buffer size) regardless of packet size, which might lead to losing data if you have more than one packet in queue.

    Proper solution is to read header (full or partial) first, decode packet len from it and then read rest of the packet (leaving other messages in the queue)

    As I always preferred example to a pure theory - I'll stick to that:

    This is my usual code (read all data in the queue)

    data=ExistingConnection.recv(BUFFER_SIZE)
    #suspect more data (try to get it all without stopping if no data)
    if (len(data)==BUFFER_SIZE):
        while 1:
            try:
                data+=ExistingConnection.recv(BUFFER_SIZE, socket.MSG_DONTWAIT)
            except:
                #error means no more data
                break
    return data
    

    but it will do stupid things if you have multiple messages.
    Better way is to do something like (example is Diameter specific)

    inB=ExistingConnection.recv(4)
    # First byte is version (1)
    # Next 3 bytes are len
    if len(inB)==0:
        return ''
    if inB[0]!='\x01':
        return ERROR
    mlen=decode_Unsigned24(inB[1:4])
    return inB+ExistingConnection.recv(mlen-4)
    

    But even this is not correct. When I tested this on a big packets (64K+, actually it started arround 25K), it failed. So, the correct solution is

    inB = ExistingConnection.recv(4)
    mlen = decode_Unsigned24(inB[1:4])
    while len(inB) < mlen:
        inB = ''.join([inB, ExistingConnectionn.recv(mlen-4)])
    return inB
    
     

    Last edit: Sergej Srepfler 2015-03-28
  • L.Belov

    L.Belov - 2014-04-18

    The practical example of testing Gx functionality by using PCRF simulator on basis of portable pyprotosim software.

    Example is given for Linux Ubuntu, python 2.7 is installed.

    1. Download and unzip the software
    2. Go to directory PCRF_sim
    3. chmod +x *.py

    ./PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py

    To stop it, run CTRL+C

    *Optionally, if you want to start PCRF simulator as a daemon, you can install and use zdaemon utility:

    a) sudo apt-get install python-zdaemon

    b) START pcrf simulator as daemon:

    zdaemon -p "python PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py" -d start

    daemon process started, pid=4641

    c) verify that it is running as a daemon:

    ps -efl | grep PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py

    1 S pcef 4639 1 0 80 0 - 5645 poll_s 15:31 ? 00:00:00 /usr/bin/python /usr/bin/zdaemon -S schema.xml -b 10 -s zdsock -m 022 -x 0,2 python PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py
    0 S pcef 4641 4639 0 80 0 - 6176 poll_s 15:31 ? 00:00:00 python PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py
    0 S pcef 4649 2189 0 80 0 - 1097 pipe_w 15:31 pts/1 00:00:00 grep --color=auto PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py

    c) TO STOP pcrf simulator, run command:

    zdaemon -p "python PCRF_SIMULATOR_GX_SERVER_WITH_SPR.py" -d stop

    4) verify that it is stopped:

    ps -efl | grep PCRF_SIMULATOR_GX_SERVER

    0 S pcef 4617 2189 0 80 0 - 1097 pipe_w 15:17 pts/1 00:00:00 grep --color=auto PCRF_SIMULATOR_GX_SERVER

    RUNNING TEST:

    In your PCRF_sim directory:

    1. Examine the test scenario in script tests_PGW_CCR_RAR_Gx_client.py
    2. Capture diameter traffic using tshark or tcpdump

    sudo tcpdump -i any -vvv -w /tmp/diam.cap port 3868 or port 3869

    Test scenario:

    Capabilities exchange between hosts:

    1) PCEF ---> CER -----> PCRF
    2) PCEF <--- CEA <----- PCRF

    PCEF sends CCR Initial request to PCRF, PCRF checks if user identity is valid in SPR DB . (The SPR DB is implemented as python dictionary with key of user's identity).
    PCRF reply with PCC Charging-Install Rule and QoS profile settings 'basic' for this user.

    3) PCEF ---> CCR-I ---> PCRF
    4) PCRF ---> SPR
    5) PCEF <--- CCA-I <-- PCRF <--- SPR (PCC rule)

    Now PCRF will send to PCEF RAR-U (Update) (Push operation) by using script called test_push_RAR-U.py (manually on Windows) (or you can send it automatically by uncommenting subprocess.call("./test_push_RAR-U.py" string in script)) with PCC-Charging-Remove old rule 'basic' and installs new PCC Charging-Install Rule and QoS profile settings 'highspeed' for this user. PCEF will reply with RAA 2001 OK reply and should enforce this policy (install new settings for this user).

    6) PCEF <--- RAR-U <--- PCRF

    7) PCEF ---> RAA ---> PCRF

    In terminal , you will see the following decoded AVP entries for Re-Auth Request:

    Decoded AVP (u'Charging-Rule-Remove', [(u'Charging-Rule-Base-Name', u'basic')])
    Decoded AVP (u'Charging-Rule-Install', [(u'Charging-Rule-Base-Name', u'highspeed')])

    Now user is logged off and PCEF informs PCRF by sending CCR-T (Terminate) to it, PCRF will terminate user session and reply with 2001 Success.

    8) PCEF ---> CCR-T ---> PCRF
    9) PCEF <--- CCA <--- PCRF

    Disconnect Pear Request to PCRF and 2001 Success Answer and close peer. ( PCRF simulator just reply with 2001 OK)

    10) PCEF ---> DPR ----> PCRF
    11) PCEF <--- DPA <---- PCRF

    The tcpdump capture communication details:

    pcef@pcef:~$ tshark -r /tmp/diam.cap -R 'diameter'

    CER/CEA

    4 0.014687 127.0.0.1 -> 127.0.0.1 DIAMETER 224 cmd=Capabilities-ExchangeRequest(257) flags=R--- appl=Diameter Common Messages(0) h2h=53511f9a e2e=fcd0000
    6 0.033021 127.0.0.1 -> 127.0.0.1 DIAMETER 228 cmd=Capabilities-ExchangeAnswer(257) flags=---- appl=Diameter Common Messages(0) h2h=53511f9a e2e=fcd0000

    CCR-I/CCA-I

    8 0.082948 127.0.0.1 -> 127.0.0.1 DIAMETER 364 cmd=Credit-ControlRequest(272) flags=RP-- appl=3GPP Gx(16777238) h2h=53511f9b e2e=fcd0001
    10 0.242987 127.0.0.1 -> 127.0.0.1 DIAMETER 532 cmd=Credit-ControlAnswer(272) flags=---- appl=3GPP Gx(16777238) h2h=53511f9b e2e=fcd0001

    RAR-U/RAA-U

    17 0.646213 127.0.0.1 -> 127.0.0.1 DIAMETER 632 cmd=Re-AuthRequest(258) flags=RP-- appl=3GPP Gx(16777238) h2h=53511f9a e2e=fcd0000
    22 1.089809 127.0.0.1 -> 127.0.0.1 DIAMETER 288 cmd=Re-AuthAnswer(258) flags=---- appl=3GPP Gx(16777238) h2h=53511f9a e2e=fcd0000

    CCR-T/CCA-T

    24 1.115780 127.0.0.1 -> 127.0.0.1 DIAMETER 364 cmd=Credit-ControlRequest(272) flags=RP-- appl=3GPP Gx(16777238) h2h=53511f9c e2e=fcd0002
    26 1.195397 127.0.0.1 -> 127.0.0.1 DIAMETER 284 cmd=Credit-ControlAnswer(272) flags=---- appl=3GPP Gx(16777238) h2h=53511f9c e2e=fcd0002

    DPR/DPA

    28 1.233210 127.0.0.1 -> 127.0.0.1 DIAMETER 152 cmd=Disconnect-PeerRequest(282) flags=R--- appl=Diameter Common Messages(0) h2h=53511f9d e2e=fcd0003
    30 1.238829 127.0.0.1 -> 127.0.0.1 DIAMETER 152 cmd=Disconnect-PeerAnswer(282) flags=---- appl=Diameter Common Messages(0) h2h=53511f9d e2e=fcd0003

     
  • Sergej Srepfler

    Sergej Srepfler - 2015-03-28

    Some thoughts about using Wireshark dictionary as suggested by Yordan Tsolov and Jarko Asenov.

    It makes sense. It even solves some of the issues and confusion I had. And it is confusing to have naming mismatch between wireshark and your code. It did not bother me, but some users seemed to be stunned.

    But offered solution is not ideal. If we use wireshark dictionary, then we also must introduce methods to override some values (e.g if MandatoryFlag is defined as MAY, then we must be able to set it to desired value for that AVP)

    So I'm really inclined to use offered solution, but after some redesign and internal cleanup.
    Unfortunately, it seems that it might break compatibility (at least with the current idea I'm having).
    So - wish me enough free time to start working on it.

     

    Last edit: Sergej Srepfler 2015-03-28
  • Sergej Srepfler

    Sergej Srepfler - 2015-04-15

    Directly using wireshark dictionary seems less and less a possibility.
    For example, you encounter stuff like

    <avp name="Auth-Application-Id" code="258" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot">
    <type type-name="AppId"/>
    <enum name="3GPP Gx" code="16777224"/>
    <enum name="3GPP Gx" code="16777238"/>

    which is perfectly OK for decoding, but NOT for encoding
    As I said - whoever allowed duplicate names in dictionary should be shot!
    And wireshark does not use hierarchical structure with dictionary per application-id, but one flat table (loaded from several files)

     
  • Ajay Mare

    Ajay Mare - 2015-10-16

    Team i am trying to use Protocal Simulator for EAP-AKA testing using wx inerface, however TCP session is coming up between Radius and Simulator when i connect a mobile client its getting error out with the below logs.

    INFO:root:('Single AVP', 'L', 12, 12, 'D', '0000010a4000000c000028af')
    INFO:root:('Single AVP', 'L', 12, 12, 'D', '000001024000000c01000031')
    INFO:root:('Decoded as', u'Vendor-Id', 10415)
    INFO:root:('Decoded as', u'Auth-Application-Id', 16777265)
    INFO:root:('Decoded as', u'Vendor-Specific-Application-Id', [(u'Vendor-Id', 10415), (u'Auth-Application-Id', 16777265)])
    Traceback (most recent call last):
    File "HSS_simulator_single.py", line 391, in <module>
    if handle_HSS(r)==ERROR:
    File "HSS_simulator_single.py", line 43, in handle_HSS
    ret=process_request(data.encode("hex"))
    File "HSS_simulator_single.py", line 288, in process_request
    return create_MAA(H)
    File "HSS_simulator_single.py", line 233, in create_MAA
    Auth_Method=findAVP("Authentication-Method",Auth_Data)
    File "../libDiameter.py", line 669, in findAVP
    for avp in list:
    TypeError: 'int' object is not iterable
    Portal-Server HSS_sim #
    Portal-Server HSS_sim #

    Portal-Server HSS_sim # python
    Python 2.7.6 (default, Jun 22 2015, 17:58:13)
    [GCC 4.8.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.

    Can some plese tell me wats the issue here.

     
    • Sergej Srepfler

      Sergej Srepfler - 2015-10-17

      Something is wrong here. Easiest way is to send me snoop+source whatever
      you are testing, so I can reproduce it.

      On the first look (always hard without context) it seems that your MAR Request over Wx interface does not contain required AVP (Authentication-Method).
      To confirm it, make network capture of incoming diameter packet.

       

      Last edit: Sergej Srepfler 2015-10-19
  • Ajay Mare

    Ajay Mare - 2015-10-19

    Can you please find the attached Capture at HSS_SIM, here i am uisng version pyprotosim-0.3.2

    Can you please tell me whats the Authentication-Method we are expecting so that we can use static value to bypass this error,
    here i am testing EAP-AKA using Mobile clients.

     

    Last edit: Ajay Mare 2015-10-19
  • Sergej Srepfler

    Sergej Srepfler - 2015-10-19

    OK. Let me state clearly how I undestood your issue:
    You have a RADIUS client.
    Radius client connect to <something> (port 1812 as expected)
    <something> then should connect to HSS_SIM over Wx interface and exchange MAR/MAA?
    But I do not see it in snoop (Capture_at_HSS_SIM.pcap). All I see is SSH encrypted traffic
    As next step, <something> sends challenge to a Radius client (using Protected EAP (EAP-PEAP code 25, which my EAP library does not support yet))

    Did I get it right? Is this the scenario you are testing?

    In that case, you have several issues:
    - EAP-PEAP is NOT supported yet. Yes, it can be done, but current version does not support it.
    - If you are using PEAP, then you should use MSCHAPv2 (another protocol currently not supported).
    - If you plan to test EAP-AKA, then you need to figure out why <something> is sending wrong EAP protocol.

    Getting authentication vector over Wx is rather simple:
    For EAP-SIM Multimedia-Auth Request looks like this:

    MAR 303, ApplicationId= 16777219
    (u'Session-Id', u'1316636797;449;137219838')
    (u'Vendor-Specific-Application-Id', [(u'Vendor-Id', 10415), (u'Auth-Application-Id', 16777219)])
    (u'Auth-Session-State', 1)
    (u'User-Name', u'734043000257998')
    (u'3GPP-SIP-Number-Auth-Items', 3)
    (u'3GPP-SIP-Auth-Data-Item',
    (u'Authentication-Method', 0)
    )
    (u'NAS-Port-Type', 5)
    (u'Origin-Host', 'aaa.test.lab')
    (u'Origin-Realm', 'test.lab')
    (u'Destination-Realm', 'remote.lab')

    For EAP-AKA:
    MAR 303, ApplicationId= 16777265
    (u'Session-Id', u'1316636797;449;137219838')
    (u'RAT-Type', 0)
    (u'ANID', u'HRPD')
    (u'Destination-Host', 'hss.remote.lab')
    (u'Destination-Realm', 'remote.lab')
    (u'Vendor-Specific-Application-Id',
    (u'Vendor-Id', 10415),
    (u'Auth-Application-Id', 16777265)
    )
    (u'User-Name', u'123423803567005')
    (u'3GPP-SIP-Number-Auth-Items', 1)
    (u'3GPP-SIP-Auth-Data-Item', [(u'3GPP-SIP-Authentication-Scheme', u'EAP-AKA')])
    (u'Auth-Session-State', 1)
    (u'Origin-Host', 'aaa.test.lab')
    Decoded AVP (u'Origin-Realm', 'test.lab')

    HSS simulator has response hardcoded: it will ALWAYS return the same vectors for ANY username.

    If you want - please let's move this into private discussion. Use my email directly for faster issue resolution.

     

    Last edit: Sergej Srepfler 2015-10-19
  • Naseem Rahman

    Naseem Rahman - 2021-04-07

    Trying to run on python 3.6.8 and getting error. Any one tried diameter_client.py in version 3.6 > ?

     
    • Sergej Srepfler

      Sergej Srepfler - 2021-04-08

      Old python2 code is not directly compatible with new python 3 code
      Supported python is clearly marked by folder name in latest release (py2, py3)
      For a working py3 diameter client, take a look at the source code folder
      https://sourceforge.net/p/pyprotosim/code-0/ci/default/tree/py3/sample/

       
  • Naseem Rahman

    Naseem Rahman - 2021-04-12

    For Python3 version, Is there a tool_EAP_decode.py ?

     
    • Sergej Srepfler

      Sergej Srepfler - 2021-04-13

      It seems to be missing from the repo. I need to check for it on my dev
      machine.
      Within a few days, I'll upload the new one (I'll wrote new one if this one
      does not work)
      Thanks for finding this problem for me.

       

      Last edit: Sergej Srepfler 2021-04-14
      • Naseem Rahman

        Naseem Rahman - 2021-04-14

        Appreciate if you could upload the EAP decode tool. Thanks!

         
        • Sergej Srepfler

          Sergej Srepfler - 2021-04-14

          New version with included tool is there.

           
  • Naseem Rahman

    Naseem Rahman - 2021-04-27

    Anyone having issue compiling the eapcalc? I am getting error, I install python-devel .
    ./py3/src_cEap/cEap.c:13:10: fatal error: Python.h: No such file or directory

     

    Last edit: Naseem Rahman 2021-04-27
    • Sergej Srepfler

      Sergej Srepfler - 2021-04-28

      Are you compiling for linux on windows?
      Please make sure that you include correct path to python.h in build script (compile.sh)
      Path is hardcoded for my machine, Change it to match your setup
      Also check that you have all required programs/packages installed (listed in comments)

      I'll assume that you work on linux
      In script, I use python 3.6, so if you use newer python, please adjust path from
      CFLAGS3="-O2 -Wall -fPIC -I/usr/include/python3.6 -shared"
      to something matching your setup

       
  • Naseem Rahman

    Naseem Rahman - 2021-10-31

    Anyone has any script that calculate EAP SIM in pythonv3?

     
    • Sergej Srepfler

      Sergej Srepfler - 2021-10-31

      See test_eap in py3/test folder

      If you are still stuck, explain exactly what you are trying to do (or
      better yet, send me what you got so far so I can make your test code
      working)

      I added the EAP-AKA client demo (EAP-SIM was not needed by OP).

       

      Last edit: Sergej Srepfler 2021-11-07
  • Naseem Rahman

    Naseem Rahman - 2022-01-07

    Hi Sergej,
    I am trying to add Emergency-Services AVP ( msg.add("Emergncy-Services", 1) but getting error :
    Exception: ('Unable to find AVP', 'Emergncy-Services', 'None'). Do I need to update my Wireshark?

     
    • Sergej Srepfler

      Sergej Srepfler - 2022-01-08

      Please check in wireshark dictionary folder if that AVP exist. If not -
      then you need to add it yourself or update

      In my dictionary (...wireshark/diameter/dictionary.xml) it is
      <avp name="Emergency-Services" code="1538" mandatory="mustnot" may-encrypt="no" vendor-bit="must" vendor-id="TGPP">
      So you might need to add vendor to the line
      msg.add("Emergency-Services", 1, "TGPP")
      or
      msg.add("Emergency-Services", 1, vendor="TGPP")</avp>

      Note:
      AVP is named "Emergency-Services" in my dict (not "Emergncy-Services").
      No spaces allowed in vendor="TGPP" (python named parameter syntax)

       

      Last edit: Sergej Srepfler 2022-01-09

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.