hi. thanks for freeradius. we converted from Radiator to freeradius and were able to halve the size of our radius cluster while still handling more load.
we're using multiple detail files defined in radiusd.conf, which then sites-enabled/default defines as redundant-load-balance, so accounting gets written to them round-robin by freeradius. then we have another sites-enabled/ "site" defining multiple servers each listen to one of the accounting files and Proxy-To-Realm them to a realm which is defined in proxy.conf. the realm in proxy.conf has home_servers and home_server_pools defined for multiple different realms, each sending to different proxy sinks. some sinks are just one host, some are multiple. this all works pretty much great, except when a proxy-sink fails to ACK the accounting we send it (thus being seen as dead or zombie). there are a small number of cases where we would love it if we could just /dev/null this proxy accounting if the remote server is dead/zombie, however i haven't figured out a way to actually configure this. it seems like i want to use a "fallback" server in the home_server_pool, where that fallback server would just 'ok' accounting or otherwise toss it in the trash, but after a few iterations of trying to make this work i have come up empty handed. if anyone can help, i'd be enormously grateful. here are the sanitized configs. so for example, i'd like to add a virtual server to the 'home_server_pool proxy-whatever' that would toss the accounting from the detail file into /dev/null for whatever period of fime site-1 and site-2 were dead/zombie. [proxy.conf] ------------------------------------------------------------------------------ # $Id: proxy.conf 34303 2011-10-26 20:31:34Z jrrs $ # This entry controls the behavior towards ALL other servers we proxy # requests to. proxy server { # Never, ever fall back to the DEFAULT realm when no # home servers are alive for a given ream. default_fallback = no } home_server proxy-whatever01-site-1 { type = acct ipaddr = 1.1.1.1 port = 1845 secret = "zz" status_check = none response_window = 10 } home_server proxy-whatever01-site-2 { type = acct ipaddr = 2.2.2.2 port = 1845 secret = "zz" status_check = none response_window = 10 } home_server_pool proxy-whatever { type = fail-over home_server = proxy-whatever01-site-1 home_server = proxy-whatever01-site-2 } realm proxy-whatever { acct_pool = proxy-whatever nostrip } [sites-enabled/default] # $Id: default 34587 2011-11-15 22:45:31Z jrrs $ authorize { preprocess update request { Client-IP-Address := "%{Client-IP-Address}" } chap mschap suffix perl switch "%{Auth-Type}" { case 'sql.auth.wifi.site3' { redundant { sql.auth.wifi.site2 sql.auth.wifi.site1 } } case 'sql.auth.wifi.site2' { redundant { sql.auth.wifi.site2 sql.auth.wifi.site1 } } case 'sql.auth.wifi.site1' { redundant { sql.auth.wifi.site1 sql.auth.wifi.site2 } } } pap } authenticate { Auth-Type PAP { pap } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap } Auth-Type ldap.site3 { redundant { ldap.site3 ldap.site2 ldap.site1 } } Auth-Type ldap.site2 { redundant { ldap.site2 ldap.site1 ldap.site3 } } Auth-Type ldap.site1 { redundant { ldap.site1 ldap.site2 ldap.site3 } } } preacct { perl } accounting { perl redundant-load-balance { detail.proxy-whatever0 detail.proxy-whatever1 detail.proxy-whatever2 detail.proxy-whatever3 detail.proxy-whatever4 } attr_filter.accounting_response } session { } post-auth { Post-Auth-Type REJECT { sql.authlog attr_filter.access_reject } } pre-proxy { } post-proxy { if ("%{proxy-reply:Packet-Type}" == "Access-Accept") { attr_filter.post-proxy } } [sites-enabled/proxy-tee] # $Id: proxy-tee 34011 2011-10-18 02:35:39Z jrrs $ server buffered-proxy-whatever0 { listen { type = detail filename = ${radacctdir}/proxy-whatever0 load_factor = 100 } preacct { if ("%{%{#User-Name}:-0}" <= 63 && "%{User-Name}" != "@") { attr_filter.proxy_whatever update control { Proxy-To-Realm := "proxy-whatever" } } } accounting { ok } } server buffered-proxy-whatever1 { listen { type = detail filename = ${radacctdir}/proxy-whatever1 load_factor = 100 } preacct { if ("%{%{#User-Name}:-0}" <= 63 && "%{User-Name}" != "@") { attr_filter.proxy_whatever update control { Proxy-To-Realm := "proxy-whatever" } } } accounting { ok } } server buffered-proxy-whatever2 { listen { type = detail filename = ${radacctdir}/proxy-whatever2 load_factor = 100 } preacct { if ("%{%{#User-Name}:-0}" <= 63 && "%{User-Name}" != "@") { attr_filter.proxy_whatever update control { Proxy-To-Realm := "proxy-whatever" } } } accounting { ok } } server buffered-proxy-whatever3 { listen { type = detail filename = ${radacctdir}/proxy-whatever3 load_factor = 100 } preacct { if ("%{%{#User-Name}:-0}" <= 63 && "%{User-Name}" != "@") { attr_filter.proxy_whatever update control { Proxy-To-Realm := "proxy-whatever" } } } accounting { ok } } server buffered-proxy-whatever4 { listen { type = detail filename = ${radacctdir}/proxy-whatever4 load_factor = 100 } preacct { if ("%{%{#User-Name}:-0}" <= 63 && "%{User-Name}" != "@") { attr_filter.proxy_whatever update control { Proxy-To-Realm := "proxy-whatever" } } } accounting { ok } } server buffered-proxy-whatever-catchup { listen { type = detail filename = ${radacctdir}/proxy-whatever-catchup load_factor = 100 } preacct { if ("%{%{#User-Name}:-0}" <= 63 && "%{User-Name}" != "@") { attr_filter.proxy_whatever update control { Proxy-To-Realm := "proxy-whatever" } } } accounting { ok } } [radiusd.conf] ------------------------------------------------------------------------------ # -*- text -*- ## ## radiusd.conf -- FreeRADIUS server configuration file. ## ## http://www.freeradius.org/ ## $Id: radiusd.conf.in,v 1.272 2008/04/26 15:14:33 aland Exp $ ## prefix = /usr exec_prefix = /usr sysconfdir = /etc localstatedir = /var sbindir = ${exec_prefix}/sbin logdir = /var/log/freeradius raddbdir = /etc/freeradius radacctdir = ${logdir}/radacct confdir = ${raddbdir} run_dir = ${localstatedir}/run/freeradius db_dir = ${raddbdir} libdir = /usr/lib/freeradius pidfile = ${run_dir}/freeradius.pid user = freerad group = freerad max_request_time = 30 cleanup_delay = 5 max_requests = 131072 listen { type = auth ipaddr = * port = 0 } listen { ipaddr = * port = 0 type = acct } hostname_lookups = no allow_core_dumps = no regular_expressions = yes extended_expressions = yes log syslog { destination = syslog syslog_facility = daemon stripped_names = no auth = no auth_badpass = no auth_goodpass = no } checkrad = ${sbindir}/checkrad security { max_attributes = 200 reject_delay = 0 status_server = yes } proxy_requests = yes $INCLUDE proxy.conf $INCLUDE clients.conf thread pool { start_servers = 32 max_servers = 160 min_spare_servers = 16 max_spare_servers = 32 max_requests_per_server = 0 } modules { pap { auto_header = no } chap { authtype = CHAP } mschap { } ldap ldap.site3 { server = "ldap.pool.example.com ldap.site3.example.com" identity = "cn=Radiusd,o=example" password = "xx" basedn = "o=nonexistent" ldap_connections_number = 3 timeout = 6 timelimit = 5 net_timeout = 1 dictionary_mapping = ${confdir}/ldap.attrmap password_attribute = userPassword } ldap ldap.site2 { server = "ldap.pool.example.com ldap.site2.example.com" identity = "cn=Radiusd,o=example" password = "xx" basedn = "o=nonexistent" ldap_connections_number = 3 timeout = 6 timelimit = 5 net_timeout = 1 dictionary_mapping = ${confdir}/ldap.attrmap password_attribute = userPassword } ldap ldap.site1 { server = "ldap.pool.example.com ldap01.vip.example.com ldap02.vip.example.com" identity = "cn=Radiusd,o=example" password = "xx" basedn = "o=nonexistent" ldap_connections_number = 3 timeout = 6 timelimit = 5 net_timeout = 1 dictionary_mapping = ${confdir}/ldap.attrmap password_attribute = userPassword } perl { module = /etc/freeradius/IT_group.pm func_authorize = authorize func_preacct = preacct func_accounting = accounting max_clones = 160 start_clones = 32 min_spare_clones = 16 max_spare_clones = 32 cleanup_delay = 5 max_request_per_clone = 0 } realm suffix { format = suffix delimiter = "@" } preprocess { } detail detail.proxy-whatever0 { detailfile = ${radacctdir}/proxy-whatever0 detailperm = 0640 header = "%t" } detail detail.proxy-whatever1 { detailfile = ${radacctdir}/proxy-whatever1 detailperm = 0640 header = "%t" } detail detail.proxy-whatever2 { detailfile = ${radacctdir}/proxy-whatever2 detailperm = 0640 header = "%t" } detail detail.proxy-whatever3 { detailfile = ${radacctdir}/proxy-whatever3 detailperm = 0640 header = "%t" } detail detail.proxy-whatever4 { detailfile = ${radacctdir}/proxy-whatever4 detailperm = 0640 header = "%t" } sql_log sql.authlog { path = "${logdir}/failedauth/%Y%m%d-%H" Post-Auth = "%l %{NAS-IP-Address} %{%{reply:Reply-Message}:-%{Module-Failure-Message}} %{User-Name} %{%{User-Password}:-%{Chap-Password}}" } sql sql.acct { database = "mysql" driver = "rlm_sql_${database}" server = "write.sql.example.com" login = "radiusd" password = "yy" radius_db = "radius" acct_table = "ACCOUNTING" sqltrace = no sqltracefile = ${logdir}/sqltrace.sql num_sql_socks = 5 connect_failure_retry_delay = 5 lifetime = 0 max_queries = 0 sql_user_name = "%{User-Name}" accounting_start_query = " \ INSERT INTO ${acct_table} ( \ USERNAME, TIME_STAMP, ACCTSTATUSTYPE, ACCTDELAYTIME, \ ACCTINPUTOCTETS, ACCTOUTPUTOCTETS, ACCTSESSIONID, \ ACCTSESSIONTIME, ACCTTERMINATECAUSE, NASIP, NASPORT, \ FRAMEDIPADDRESS, CALLED_STATION, CALLING_STATION \ ) VALUES( \ '%{SQL-User-Name}', '%l', '%{Acct-Status-Type}', \ '%{Acct-Delay-Time}', '%{Acct-Input-Octets}', \ '%{Acct-Output-Octets}', '%{Acct-Session-Id}', \ '%{Acct-Session-Time}', '%{Acct-Terminate-Cause}', \ '%{NAS-IP-Address}', '%{NAS-Port}', \ '%{Framed-IP-Address}', '%{Called-Station-Id}', \ '%{Calling-Station-Id}');" accounting_stop_query = " \ INSERT INTO ${acct_table} ( \ USERNAME, TIME_STAMP, ACCTSTATUSTYPE, ACCTDELAYTIME, \ ACCTINPUTOCTETS, ACCTOUTPUTOCTETS, ACCTSESSIONID, \ ACCTSESSIONTIME, ACCTTERMINATECAUSE, NASIP, NASPORT, \ FRAMEDIPADDRESS, CALLED_STATION, CALLING_STATION \ ) VALUES( \ '%{SQL-User-Name}', '%l', '%{Acct-Status-Type}', \ '%{Acct-Delay-Time}', '%{Acct-Input-Octets}', \ '%{Acct-Output-Octets}', '%{Acct-Session-Id}', \ '%{Acct-Session-Time}', '%{Acct-Terminate-Cause}', \ '%{NAS-IP-Address}', '%{NAS-Port}', \ '%{Framed-IP-Address}', '%{Called-Station-Id}', \ '%{Calling-Station-Id}')" } sql sql.auth.wifi.site2 { database = "mysql" driver = "rlm_sql_${database}" server = "3.3.3.3" login = "radiusd" password = "yy" num_sql_socks = 3 connect_failure_retry_delay = 60 radius_db = "backend" authcheck_table = "wifi_users" authreply_table = "wifi_users" sqltrace = no sqltracefile = ${logdir}/sqltrace.sql sql_user_name = "%{User-Name}" authorize_check_query = " \ SELECT NULL as id, \ '%{SQL-User-Name}' as username, \ 'Cleartext-Password' AS attribute, \ userPassword AS value, \ ':=' AS op \ FROM ${authcheck_table} \ WHERE uid = '%{SQL-User-Name}'" authorize_reply_query = " \ SELECT NULL as id, \ '%{SQL-User-Name}' as username, \ 'Whatever-Service-Bundle' AS attribute, \ serviceType AS value, \ ':=' AS op \ FROM ${authcheck_table} \ WHERE uid = '%{SQL-User-Name}'" } sql sql.auth.wifi.site1 { database = "mysql" driver = "rlm_sql_${database}" server = "authread.sql.example.com" login = "radiusd" password = "yy" num_sql_socks = 3 connect_failure_retry_delay = 60 radius_db = "backend" authcheck_table = "wifi_users" authreply_table = "wifi_users" sqltrace = no sqltracefile = ${logdir}/sqltrace.sql sql_user_name = "%{User-Name}" authorize_check_query = " \ SELECT NULL as id, \ '%{SQL-User-Name}' as username, \ 'Cleartext-Password' AS attribute, \ userPassword AS value, \ ':=' AS op \ FROM ${authcheck_table} \ WHERE uid = '%{SQL-User-Name}'" authorize_reply_query = " \ SELECT NULL as id, \ '%{SQL-User-Name}' as username, \ 'Whatever-Service-Bundle' AS attribute, \ serviceType AS value, \ ':=' AS op \ FROM ${authcheck_table} \ WHERE uid = '%{SQL-User-Name}'" } attr_filter attr_filter.pre-proxy { attrsfile = ${confdir}/attrs.pre-proxy } attr_filter attr_filter.post-proxy { attrsfile = ${confdir}/attrs.post-proxy } attr_filter attr_filter.access_reject { key = %{User-Name} attrsfile = ${confdir}/attrs.access_reject } attr_filter attr_filter.accounting_response { key = %{User-Name} attrsfile = ${confdir}/attrs.accounting_response } attr_filter attr_filter.proxy_whatever { key = "DEFAULT" attrsfile = ${confdir}/attrs.proxy_whatever } always ok { rcode = ok } } $INCLUDE sites-enabled/ -- jared - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html