diff --git a/cgrates.json b/cgrates.json index 6fac9ad..7880fc2 100644 --- a/cgrates.json +++ b/cgrates.json @@ -1,132 +1,127 @@ { -// CGRateS Configuration file -// +// CGRateS Configuration for PPPoE RADIUS Authentication - PAP +// Single processor approach - fetches password from AttributeS, strips nulls, compares +// Bypasses *radauth null-padding bug by using filter-based comparison "general": { "log_level": 7, + "node_id": "pppoe_auth_server", + "default_tenant": "cgrates.org" }, - "listen": { - "rpc_json": ":2012", // RPC JSON listening address - "rpc_gob": ":2013", // RPC GOB listening address - "http": ":2080", // HTTP listening address + "rpc_json": "127.0.0.1:2012", + "rpc_gob": "127.0.0.1:2013", + "http": "127.0.0.1:2080" }, -"data_db": { - "db_type": "redis", - "db_port": 6379, - "db_name": "10", +"data_db": { + "db_type": "*internal" }, -"stor_db": { // database used to store offline tariff plans and CDRs - "db_password": "CGRateS.org", // password to use when connecting to stordb -}, -"filters": { - "apiers_conns": ["*localhost"], +"stor_db": { + "db_type": "*internal" }, -"rals": { - "enabled": true, +"caches":{ + "partitions": { + "*attribute_profiles": {"limit": -1, "ttl": "1h"}, + "*attribute_filter_indexes": {"limit": -1, "ttl": "1h"} + } }, -"schedulers": { - "enabled": true, -}, - -"cdrs": { - "enabled": true, - "rals_conns": ["*internal"], -}, - -"resources": { - "enabled": true, +"filters": { + "apiers_conns": ["*localhost"] }, "attributes": { - "enabled": true, -}, - -"routes": { - "enabled": true, + "enabled": true, + "apiers_conns": ["*localhost"], + "indexed_selects": true, + "prefix_indexed_fields": ["*req.Account"] }, "chargers": { - "enabled": true, + "enabled": true }, "sessions": { - "enabled": true, - "attributes_conns": ["*localhost"], - "cdrs_conns": ["*localhost"], - "rals_conns": ["*localhost"], - "resources_conns": ["*localhost"], - "chargers_conns": ["*internal"], - "debit_interval": "10s", + "enabled": true, + "attributes_conns": ["*localhost"], + "chargers_conns": ["*internal"], + "debit_interval": "0" }, + "radius_agent": { - "enabled": true, - "sessions_conns": ["*localhost"], - "listeners":[ - { - "network": "udp", - "auth_address": "0.0.0.0:1812", - "acct_address": "0.0.0.0:1813" - } - ], - "client_secrets": { - "*default": "CGRateS.org" - }, - "client_dictionaries": { - "*default": ["/usr/share/cgrates/radius/dict/"] - }, - "request_processors": [ - { - "id": "CGRPAPAuth", - "filters": ["*string:~*vars.*radReqType:*radAuth"], - "flags": ["*authorize", "*attributes", "*accounts", "*continue", "*log"], - "request_fields": [ - {"tag": "Category", "path": "*cgreq.Category", "type": "*constant", "value": "call"}, - {"tag": "RequestType", "path": "*cgreq.RequestType", "type": "*constant", "value": "*prepaid", "mandatory": true}, - {"tag": "OriginID", "path": "*cgreq.OriginID", "type": "*composed", "value": "~*req.Acct-Session-Id", "mandatory": true}, - {"tag": "Account", "path": "*cgreq.Account", "type": "*composed", "value": "~*req.User-Name", "mandatory": true}, - {"tag": "Subject", "path": "*cgreq.Subject", "type": "*composed", "value": "~*req.User-Name", "mandatory": true}, - {"tag": "Destination", "path": "*cgreq.Destination", "type": "*constant", "value": "*any", "mandatory": true}, - {"tag": "SetupTime", "path": "*cgreq.SetupTime", "type": "*composed", "value": "~*req.Event-Timestamp;*now", "mandatory": true}, - {"tag": "AnswerTime", "path": "*cgreq.AnswerTime", "type": "*composed", "value": "~*req.Event-Timestamp;*now", "mandatory": true}, - {"tag": "PasswordFromAttributes", "path": "*cgreq.PasswordFromAttributes", "type": "*constant", "value": "*attributes"} - ], - "reply_fields": [] - }, - { - "id": "RadiusPAPAuthProcessor", - "filters": ["*string:~*vars.*radReqType:*radAuth"], - "flags": ["*radauth", "*pap", "*log"], - "request_fields": [ - {"tag": "UserPassword", "path": "*vars.UserPassword", "type": "*variable", - "value": "~*cgrep.Attributes.PasswordFromAttributes"} - ], - "reply_fields": [ - {"tag": "RemoveAddedFields", "filters": ["*notempty:~*cgrep.Error:"], "type": "*removeall", "path": "*rep"}, - {"tag": "Code", "path": "*rep.*radReplyCode", "filters": ["*notempty:~*cgrep.Error:"], - "type": "*constant", "value": "AccessReject"}, - {"tag": "ReplyMessage", "path": "*rep.Reply-Message", "filters": ["*notempty:~*cgrep.Error:"], - "type": "*variable", "value": "~*cgrep.Error"}, - {"tag": "SessionTimeout", "path": "*rep.Session-Timeout", "filters": ["*empty:~*cgrep.Error:"], - "type": "*constant", "value": "3600"}, - {"tag": "AcctInterimInterval", "path": "*rep.Acct-Interim-Interval", "filters": ["*empty:~*cgrep.Error:"], - "type": "*constant", "value": "30"} - ] - } - ] + "enabled": true, + "sessions_conns": ["*localhost"], + "attributes_conns": ["*localhost"], + "listeners":[ + { + "network": "udp", + "auth_address": "0.0.0.0:1812", + "acct_address": "0.0.0.0:1813" + } + ], + "client_secrets": { + "*default": "testing123" + }, + "client_dictionaries": { + "*default": ["/usr/share/cgrates/radius/dict/"] + }, + "request_processors": [ + // ============================================================ + // Single processor for PAP authentication + // Fetches password from AttributeS, strips nulls, compares + // ============================================================ + { + "id": "PPPoE_PAP_Auth", + "filters": [ + "*string:~*vars.*radReqType:*radAuth" + ], + "flags": [ + "*authorize", + "*attributes", + "*log" + ], + "request_fields": [ + {"tag": "ToR", "path": "*cgreq.ToR", "type": "*constant", "value": "*data"}, + {"tag": "Category", "path": "*cgreq.Category", "type": "*constant", "value": "pppoe"}, + {"tag": "RequestType", "path": "*cgreq.RequestType", "type": "*constant", "value": "*none", "mandatory": true}, + {"tag": "OriginID", "path": "*cgreq.OriginID", "type": "*composed", "value": "~*req.User-Name"}, + {"tag": "Account", "path": "*cgreq.Account", "type": "*composed", "value": "~*req.User-Name", "mandatory": true}, + {"tag": "Subject", "path": "*cgreq.Subject", "type": "*composed", "value": "~*req.User-Name"}, + // Marker to fetch password from AttributeS + {"tag": "Password", "path": "*cgreq.Password", "type": "*constant", "value": "*attributes"}, + // Strip null padding from received password + {"tag": "ReceivedPassword", "path": "*vars.ReceivedPassword", "type": "*variable", + "value": "~*req.User-Password{*strip:*suffix:*nil}"} + ], + "reply_fields": [ + // Get expected password from attributes reply + {"tag": "ExpectedPassword", "path": "*vars.ExpectedPassword", "type": "*variable", + "value": "~*cgrep.Attributes.Password"}, + // SUCCESS: Passwords match - set standard PPP attributes + {"tag": "FramedProtocol", "path": "*rep.Framed-Protocol", + "filters": ["*string:~*vars.ReceivedPassword:~*vars.ExpectedPassword"], + "type": "*constant", "value": "1"}, + {"tag": "ServiceType", "path": "*rep.Service-Type", + "filters": ["*string:~*vars.ReceivedPassword:~*vars.ExpectedPassword"], + "type": "*constant", "value": "2"}, + // FAILURE: Passwords don't match or not found - reject + {"tag": "RejectCode", "path": "*rep.*radReplyCode", + "filters": ["*notstring:~*vars.ReceivedPassword:~*vars.ExpectedPassword"], + "type": "*constant", "value": "AccessReject"}, + {"tag": "RejectMessage", "path": "*rep.Reply-Message", + "filters": ["*notstring:~*vars.ReceivedPassword:~*vars.ExpectedPassword"], + "type": "*constant", "value": "Invalid username or password"} + ] + } + ] }, - - "apiers": { - "enabled": true, - "scheduler_conns": ["*internal"], -}, - + "enabled": true } +} diff --git a/cgrates.json.orig b/cgrates.json.orig new file mode 100644 index 0000000..6fac9ad --- /dev/null +++ b/cgrates.json.orig @@ -0,0 +1,132 @@ +{ +// CGRateS Configuration file +// + +"general": { + "log_level": 7, +}, + + +"listen": { + "rpc_json": ":2012", // RPC JSON listening address + "rpc_gob": ":2013", // RPC GOB listening address + "http": ":2080", // HTTP listening address +}, + +"data_db": { + "db_type": "redis", + "db_port": 6379, + "db_name": "10", +}, + +"stor_db": { // database used to store offline tariff plans and CDRs + "db_password": "CGRateS.org", // password to use when connecting to stordb +}, +"filters": { + "apiers_conns": ["*localhost"], +}, + +"rals": { + "enabled": true, +}, + +"schedulers": { + "enabled": true, +}, + +"cdrs": { + "enabled": true, + "rals_conns": ["*internal"], +}, + +"resources": { + "enabled": true, +}, + +"attributes": { + "enabled": true, +}, + +"routes": { + "enabled": true, +}, + +"chargers": { + "enabled": true, +}, + +"sessions": { + "enabled": true, + "attributes_conns": ["*localhost"], + "cdrs_conns": ["*localhost"], + "rals_conns": ["*localhost"], + "resources_conns": ["*localhost"], + "chargers_conns": ["*internal"], + "debit_interval": "10s", +}, +"radius_agent": { + "enabled": true, + "sessions_conns": ["*localhost"], + "listeners":[ + { + "network": "udp", + "auth_address": "0.0.0.0:1812", + "acct_address": "0.0.0.0:1813" + } + ], + "client_secrets": { + "*default": "CGRateS.org" + }, + "client_dictionaries": { + "*default": ["/usr/share/cgrates/radius/dict/"] + }, + "request_processors": [ + { + "id": "CGRPAPAuth", + "filters": ["*string:~*vars.*radReqType:*radAuth"], + "flags": ["*authorize", "*attributes", "*accounts", "*continue", "*log"], + "request_fields": [ + {"tag": "Category", "path": "*cgreq.Category", "type": "*constant", "value": "call"}, + {"tag": "RequestType", "path": "*cgreq.RequestType", "type": "*constant", "value": "*prepaid", "mandatory": true}, + {"tag": "OriginID", "path": "*cgreq.OriginID", "type": "*composed", "value": "~*req.Acct-Session-Id", "mandatory": true}, + {"tag": "Account", "path": "*cgreq.Account", "type": "*composed", "value": "~*req.User-Name", "mandatory": true}, + {"tag": "Subject", "path": "*cgreq.Subject", "type": "*composed", "value": "~*req.User-Name", "mandatory": true}, + {"tag": "Destination", "path": "*cgreq.Destination", "type": "*constant", "value": "*any", "mandatory": true}, + {"tag": "SetupTime", "path": "*cgreq.SetupTime", "type": "*composed", "value": "~*req.Event-Timestamp;*now", "mandatory": true}, + {"tag": "AnswerTime", "path": "*cgreq.AnswerTime", "type": "*composed", "value": "~*req.Event-Timestamp;*now", "mandatory": true}, + {"tag": "PasswordFromAttributes", "path": "*cgreq.PasswordFromAttributes", "type": "*constant", "value": "*attributes"} + ], + "reply_fields": [] + }, + { + "id": "RadiusPAPAuthProcessor", + "filters": ["*string:~*vars.*radReqType:*radAuth"], + "flags": ["*radauth", "*pap", "*log"], + "request_fields": [ + {"tag": "UserPassword", "path": "*vars.UserPassword", "type": "*variable", + "value": "~*cgrep.Attributes.PasswordFromAttributes"} + ], + "reply_fields": [ + {"tag": "RemoveAddedFields", "filters": ["*notempty:~*cgrep.Error:"], "type": "*removeall", "path": "*rep"}, + {"tag": "Code", "path": "*rep.*radReplyCode", "filters": ["*notempty:~*cgrep.Error:"], + "type": "*constant", "value": "AccessReject"}, + {"tag": "ReplyMessage", "path": "*rep.Reply-Message", "filters": ["*notempty:~*cgrep.Error:"], + "type": "*variable", "value": "~*cgrep.Error"}, + {"tag": "SessionTimeout", "path": "*rep.Session-Timeout", "filters": ["*empty:~*cgrep.Error:"], + "type": "*constant", "value": "3600"}, + {"tag": "AcctInterimInterval", "path": "*rep.Acct-Interim-Interval", "filters": ["*empty:~*cgrep.Error:"], + "type": "*constant", "value": "30"} + ] + } + ] +}, + + + +"apiers": { + "enabled": true, + "scheduler_conns": ["*internal"], +}, + +} + diff --git a/load-tariff.sh b/load-tariff.sh new file mode 100644 index 0000000..465780d --- /dev/null +++ b/load-tariff.sh @@ -0,0 +1,5 @@ + curl -X POST http://127.0.0.1:2080/jsonrpc -H "Content-Type: application/json" -d '{ + "method": "APIerSv2.LoadTariffPlanFromFolder", + "params": [{"FolderPath": "/etc/cgrates/tariffplans/new"}], + "id": 1 + }' diff --git a/tariffplans/new/Attributes.csv b/tariffplans/new/Attributes.csv new file mode 100644 index 0000000..0d9ac96 --- /dev/null +++ b/tariffplans/new/Attributes.csv @@ -0,0 +1,42 @@ +#Tenant,ID,Contexts,FilterIDs,ActivationInterval,AttributeFilterIDs,Path,Type,Value,Blocker,Weight +# PPPoE User Credentials for RADIUS PAP Authentication +# +# Format: Each user needs an attribute profile that: +# 1. Matches on Account (username) +# 2. Returns PasswordFromAttributes for PAP verification +# 3. Optionally returns session parameters (IP, rate limits, timeout) +# +# The PasswordFromAttributes field will be retrieved by the RADIUS agent +# and compared against the PAP-encoded password in the AccessRequest + +# ============================================================ +# User: pppoe_user1 - Basic user with password only +# ============================================================ +cgrates.org,ATTR_PPPOE_USER1,*sessions,*string:~*req.Account:pppoe_user1,,,*req.PasswordFromAttributes,*constant,SecurePass123,false,10 + +# ============================================================ +# User: pppoe_user2 - User with static IP assignment +# ============================================================ +cgrates.org,ATTR_PPPOE_USER2,*sessions,*string:~*req.Account:pppoe_user2,,,*req.PasswordFromAttributes,*constant,MyPassword456,false,10 +cgrates.org,ATTR_PPPOE_USER2,,,,,*req.FramedIP,*constant,10.0.0.100,, + +# ============================================================ +# User: pppoe_user3 - User with rate limiting (Mikrotik example) +# ============================================================ +cgrates.org,ATTR_PPPOE_USER3,*sessions,*string:~*req.Account:pppoe_user3,,,*req.PasswordFromAttributes,*constant,FastUser789,false,10 +cgrates.org,ATTR_PPPOE_USER3,,,,,*req.FramedIP,*constant,10.0.0.101,, +cgrates.org,ATTR_PPPOE_USER3,,,,,*req.RateLimit,*constant,10M/20M,, +cgrates.org,ATTR_PPPOE_USER3,,,,,*req.SessionTimeout,*constant,86400,, + +# ============================================================ +# User: pppoe_user4 - Premium user with higher limits +# ============================================================ +cgrates.org,ATTR_PPPOE_USER4,*sessions,*string:~*req.Account:pppoe_user4,,,*req.PasswordFromAttributes,*constant,PremiumPass!@#,false,10 +cgrates.org,ATTR_PPPOE_USER4,,,,,*req.FramedIP,*constant,10.0.0.102,, +cgrates.org,ATTR_PPPOE_USER4,,,,,*req.RateLimit,*constant,100M/100M,, +cgrates.org,ATTR_PPPOE_USER4,,,,,*req.SessionTimeout,*constant,0,, + +# ============================================================ +# User: test - Simple test user for quick verification +# ============================================================ +cgrates.org,ATTR_PPPOE_TEST,*sessions,*string:~*req.Account:test,,,*req.Password,*constant,test123,false,10 diff --git a/tariffplans/new/Attributes.csv.old b/tariffplans/new/Attributes.csv.old new file mode 100644 index 0000000..1324055 --- /dev/null +++ b/tariffplans/new/Attributes.csv.old @@ -0,0 +1,42 @@ +#Tenant,ID,Contexts,FilterIDs,ActivationInterval,AttributeFilterIDs,Path,Type,Value,Blocker,Weight +# PPPoE User Credentials for RADIUS PAP Authentication +# +# Format: Each user needs an attribute profile that: +# 1. Matches on Account (username) +# 2. Returns PasswordFromAttributes for PAP verification +# 3. Optionally returns session parameters (IP, rate limits, timeout) +# +# The PasswordFromAttributes field will be retrieved by the RADIUS agent +# and compared against the PAP-encoded password in the AccessRequest + +# ============================================================ +# User: pppoe_user1 - Basic user with password only +# ============================================================ +cgrates.org,ATTR_PPPOE_USER1,*sessions,*string:~*req.Account:pppoe_user1,,,*req.PasswordFromAttributes,*constant,SecurePass123,false,10 + +# ============================================================ +# User: pppoe_user2 - User with static IP assignment +# ============================================================ +cgrates.org,ATTR_PPPOE_USER2,*sessions,*string:~*req.Account:pppoe_user2,,,*req.PasswordFromAttributes,*constant,MyPassword456,false,10 +cgrates.org,ATTR_PPPOE_USER2,,,,,*req.FramedIP,*constant,10.0.0.100,, + +# ============================================================ +# User: pppoe_user3 - User with rate limiting (Mikrotik example) +# ============================================================ +cgrates.org,ATTR_PPPOE_USER3,*sessions,*string:~*req.Account:pppoe_user3,,,*req.PasswordFromAttributes,*constant,FastUser789,false,10 +cgrates.org,ATTR_PPPOE_USER3,,,,,*req.FramedIP,*constant,10.0.0.101,, +cgrates.org,ATTR_PPPOE_USER3,,,,,*req.RateLimit,*constant,10M/20M,, +cgrates.org,ATTR_PPPOE_USER3,,,,,*req.SessionTimeout,*constant,86400,, + +# ============================================================ +# User: pppoe_user4 - Premium user with higher limits +# ============================================================ +cgrates.org,ATTR_PPPOE_USER4,*sessions,*string:~*req.Account:pppoe_user4,,,*req.PasswordFromAttributes,*constant,PremiumPass!@#,false,10 +cgrates.org,ATTR_PPPOE_USER4,,,,,*req.FramedIP,*constant,10.0.0.102,, +cgrates.org,ATTR_PPPOE_USER4,,,,,*req.RateLimit,*constant,100M/100M,, +cgrates.org,ATTR_PPPOE_USER4,,,,,*req.SessionTimeout,*constant,0,, + +# ============================================================ +# User: test - Simple test user for quick verification +# ============================================================ +cgrates.org,ATTR_PPPOE_TEST,*sessions,*string:~*req.Account:test,,,*req.PasswordFromAttributes,*constant,test123,false,10