一、安装 freeradius 3.0
将用户信息配置在RADIUS服务器上,通过RADIUS服务器对用户进行认证。 其特点时认证和授权结合,不能分离,认证成功授权也成功。 该协议定义了基于UDP的RADIUS报文格式及其传输机制,并规定UDP端口1812,1813分别作为了认证,计费端口。 当用户输入用户名和密码,请求发给中继请求服务,将发送一个请求报文给RADIUS服务器, 这时服务器会比对其保存的账户密码,正确与否,将会发送一个接受或者拒绝报文。 通知到用户认证结果,认证成功,发送一个计费开始请求报文,服务器将回应一个开始响应报文。
apt-get install freeradius
二、配置费挑战用户
编辑/etc/freeradius/3.0/users文件,89行下面加入以下内容(89行有用户例子)
admin Cleartext-Password := "admin" admin Cleartext-Password := "click1" array Cleartext-Password := "click1"
三、freeradius 挑战认证配置过程:
1.编辑/etc/freeradius/3.0/sites-enabled/default 文件中加入下面这段
ip根据自己的环境去修改
server foo { listen { ipaddr = 192.168.120.218 port = 2000 type = auth } listen { ipaddr = 182.16.10.201 port = 2000 type = auth } authorize { update { control:Auth-Type := perl } perl } authenticate { perl } client private-network-1 { ipaddr = 192.168.120.0/24 secret = testing123 } }
2. 把附件 perl 放到 /etc/freeradius/3.0/mods-enabled/ 并加 777 权限, chown -R root:root perl
chown -R root:root perl
perl文件内容如下:
# -*- text -*- # # $Id: fa04cdabb71767050aaa0664da792fd6086adb19 $ # Persistent, embedded Perl interpreter. # perl { # # The Perl script to execute on authorize, authenticate, # accounting, xlat, etc. This is very similar to using # 'rlm_exec' module, but it is persistent, and therefore # faster. # filename = /etc/freeradius/3.0/perl_otp.pl # # Options which are passed to the Perl interpreter. # These are (mostly) the same options as are passed # to the "perl" command line. # # The most useful flag is "-T". This sets tainting on. And # as of 3.0.18, makes it impossible to leverage bad # User-Names into local command execution. # perl_flags = "-T" # # The following hashes are given to the module and # filled with value-pairs (Attribute names and values) # # %RAD_CHECK Check items # %RAD_REQUEST Attributes from the request # %RAD_REPLY Attributes for the reply # %RAD_REQUEST_PROXY Attributes from the proxied request # %RAD_REQUEST_PROXY_REPLY Attributes from the proxy reply # # The interface between FreeRADIUS and Perl is strings. # That is, attributes of type "octets" are converted to # printable strings, such as "0xabcdef". If you want to # access the binary values of the attributes, you should # call the Perl "pack" function. Then to send any binary # data back to FreeRADIUS, call the Perl "unpack" function, # so that the contents of the hashes are printable strings. # # IP addresses are sent as strings, e.g. "192.0.2.25", and # not as a 4-byte binary value. The same applies to other # attribute data types. # # Attributes of type "string" are copied to Perl as-is. # They are not escaped or interpreted. # # The return codes from functions in the perl_script # are passed directly back to the server. These # codes are defined in mods-config/example.pl # # You can define configuration items (and nested sub-sections) in perl "config" section. # These items will be accessible in the perl script through %RAD_PERLCONF hash. # For instance: $RAD_PERLCONF{'name'} $RAD_PERLCONF{'sub-config'}->{'name'} # #config { # name = "value" # sub-config { # name = "value of name from config.sub-config" # } #} # # List of functions in the module to call. # Uncomment and change if you want to use function # names other than the defaults. # func_authenticate = authenticate func_authorize = authorize #func_preacct = preacct #func_accounting = accounting #func_checksimul = checksimul #func_pre_proxy = pre_proxy #func_post_proxy = post_proxy #func_post_auth = post_auth #func_recv_coa = recv_coa #func_send_coa = send_coa #func_xlat = xlat #func_detach = detach # # Uncomment the following lines if you wish # to use separate functions for Start and Stop # accounting packets. In that case, the # func_accounting function is not called. # #func_start_accounting = accounting_start #func_stop_accounting = accounting_stop }
3. 把 perl_otp.pl 放到 /etc/freeradius/3.0/ 并加 777 权限
chown -R freerad:freerad perl_otp.pl /etc/freeradius/3.0/mods-enabled/ chown -R freerad:freerad perl_otp.pl
perl_otp.pl文件内容如下:
# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA # # Copyright 2002 The FreeRADIUS server project # Copyright 2002 Boian Jordanov <bjordanov@orbitel.bg> # # # Example code for use with rlm_perl # # You can use every module that comes with your perl distribution! # # If you are using DBI and do some queries to DB, please be sure to # use the CLONE function to initialize the DBI connection to DB. # #use strict; use warnings; # use ... use Data::Dumper; # Bring the global hashes into the package scope our (%RAD_REQUEST, %RAD_REPLY, %RAD_CHECK, %RAD_STATE); # This is hash wich hold original request from radius #my %RAD_REQUEST; # In this hash you add values that will be returned to NAS. #my %RAD_REPLY; #This is for check items #my %RAD_CHECK; # This is the session-sate #my %RAD_STATE; # This is configuration items from "config" perl module configuration section #my %RAD_PERLCONF; # Multi-value attributes are mapped to perl arrayrefs. # # update request { # Filter-Id := 'foo' # Filter-Id += 'bar' # } # # This results to the following entry in %RAD_REQUEST: # # $RAD_REQUEST{'Filter-Id'} = [ 'foo', 'bar' ]; # # Likewise, you can assign an arrayref to return multi-value attributes # # This the remapping of return values # use constant { RLM_MODULE_REJECT => 0, # immediately reject the request RLM_MODULE_OK => 2, # the module is OK, continue RLM_MODULE_HANDLED => 3, # the module handled the request, so stop RLM_MODULE_INVALID => 4, # the module considers the request invalid RLM_MODULE_USERLOCK => 5, # reject the request (user is locked out) RLM_MODULE_NOTFOUND => 6, # user not found RLM_MODULE_NOOP => 7, # module succeeded without doing anything RLM_MODULE_UPDATED => 8, # OK (pairs modified) RLM_MODULE_NUMCODES => 9, # How many return codes there are RLM_MODULE_CHALLENGE => 11, # How many return codes there are }; # Same as src/include/log.h use constant { L_AUTH => 2, # Authentication message L_INFO => 3, # Informational message L_ERR => 4, # Error message L_WARN => 5, # Warning L_PROXY => 6, # Proxy messages L_ACCT => 7, # Accounting messages L_DBG => 16, # Only displayed when debugging is enabled L_DBG_WARN => 17, # Warning only displayed when debugging is enabled L_DBG_ERR => 18, # Error only displayed when debugging is enabled L_DBG_WARN_REQ => 19, # Less severe warning only displayed when debugging is enabled L_DBG_ERR_REQ => 20, # Less severe error only displayed when debugging is enabled }; # Global variables can persist across different calls to the module. # # # { # my %static_global_hash = (); # # sub post_auth { # ... # } # ... # } #func_authenticate = authenticate; #func_authorize = authorize; # Function to handle authorize sub authorize { # For debugging purposes only # &log_request_attributes; # Here's where your authorization code comes # You can call another function from here: &test_call; return RLM_MODULE_OK; } # Function to handle authenticate sub authenticate { # For debugging purposes only # &log_request_attributes; if ($RAD_REQUEST{'User-Name'} =~ /^otp_test/i) { if($RAD_REQUEST{'User-Password'} =~ /hahaha/i){ $RAD_REPLY{'Reply-Message'} = "accept after challenged"; return RLM_MODULE_OK; }else{ $RAD_REPLY{'Reply-Message'} = "hahahaha"; $RAD_CHECK{'Response-Packet-Type'} = "Access-Challenge"; } return RLM_MODULE_HANDLED; } else { # Accept user and set some attribute if (&radiusd::xlat("%{client:group}") eq 'UltraAllInclusive') { # User called from NAS with unlim plan set, set higher limits $RAD_REPLY{'h323-credit-amount'} = "1000000"; } else { $RAD_REPLY{'h323-credit-amount'} = "100"; } return RLM_MODULE_OK; } } # Function to handle preacct sub preacct { # For debugging purposes only # &log_request_attributes; return RLM_MODULE_OK; } # Function to handle accounting sub accounting { # For debugging purposes only # &log_request_attributes; # You can call another subroutine from here &test_call; return RLM_MODULE_OK; } # Function to handle checksimul sub checksimul { # For debugging purposes only # &log_request_attributes; return RLM_MODULE_OK; } # Function to handle pre_proxy sub pre_proxy { # For debugging purposes only # &log_request_attributes; return RLM_MODULE_OK; } # Function to handle post_proxy sub post_proxy { # For debugging purposes only # &log_request_attributes; return RLM_MODULE_OK; } # Function to handle post_auth sub post_auth { # For debugging purposes only # &log_request_attributes; return RLM_MODULE_OK; } # Function to handle xlat sub xlat { # For debugging purposes only # &log_request_attributes; # Loads some external perl and evaluate it my ($filename,$a,$b,$c,$d) = @_; &radiusd::radlog(L_DBG, "From xlat $filename "); &radiusd::radlog(L_DBG,"From xlat $a $b $c $d "); local *FH; open FH, $filename or die "open '$filename' $!"; local($/) = undef; my $sub = <FH>; close FH; my $eval = qq{ sub handler{ $sub;} }; eval $eval; eval {main->handler;}; } # Function to handle detach sub detach { # For debugging purposes only # &log_request_attributes; } # # Some functions that can be called from other functions # sub test_call { # Some code goes here } sub log_request_attributes { # This shouldn't be done in production environments! # This is only meant for debugging! for (keys %RAD_REQUEST) { &radiusd::radlog(L_DBG, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}"); } }
4.修改client.conf文件
在目录 /etc/freeradius/3.0下,修改client.conf文件
5. service freeradius restart
测试挑战用户 otp_test/click1 挑战密码: hahahaha 配置挑战的时候端口号不是1812,而是2000