简介
目的: AC向FreeRadius服务器发送验证请求时,Radius服务器与mysql数据库认证后通过认证请求,使请求的用户可以上网。
文章结构
- FreeRadius配置
- Mysql数据库配置
- 测试
FreeRadius配置
需要配置的文件
配置文件都存放在根目录的\etc\raddb 目录下
- sites-available\default
- sites-enabled\default
- sites-enabled\inner-tunnel
- sql.conf
sites-available\default
在授权和认证中都加入sql的方式
authorize {
preprocess
chap
mschap
digest
suffix
eap {
ok = return
}
files
sql
expiration
logintime
pap
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
digest
unix
eap
sql
}
preacct {
preprocess
acct_unique
suffix
files
}
accounting {
detail
exec
attr_filter.accounting_response
}
session {
radutmp
}
post-auth {
sql
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
pre-proxy {
}
post-proxy {
eap
}
sites-enabled\default
authorize {
preprocess
chap
mschap
digest
wimax
suffix
eap {
ok = return
}
Autz-Type EAP {
eap
}
#files
expiration
logintime
pap
sql
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
digest
eap
eap2
}
preacct {
preprocess
acct_unique
suffix
files
}
accounting {
detail
#radutmp
exec
attr_filter.accounting_response
sql
}
session {
#radutmp
sql
}
post-auth {
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
}
sql
}
pre-proxy {
}
post-proxy {
eap
}
sites-enabled\inner-tunnel
server inner-tunnel {
listen {
ipaddr = 127.0.0.1
port = 18120
type = auth
}
authorize {
chap
mschap
suffix
update control {
Proxy-To-Realm := LOCAL
}
eap {
ok = return
}
sql
expiration
logintime
pap
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
eap
eap2
}
session {
#radutmp
sql
}
post-auth {
sql
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
pre-proxy {
}
post-proxy {
eap
}
}
sql.conf
配置数据库
sql {
# 配置数据库类型
database = "mysql"
driver = "rlm_sql_${database}"
# 数据库服务器IP
server = "localhost"
# 数据库服务器端口
port = 3306
# 用户名
login = "radius"
# 密码
password = "123456"
# 数据库
radius_db = "radius"
acct_table1 = "radacct"
acct_table2 = "radacct"
postauth_table = "radpostauth"
authcheck_table = "radcheck"
authreply_table = "radreply"
groupcheck_table = "radgroupcheck"
groupreply_table = "radgroupreply"
usergroup_table = "radusergroup"
deletestalesessions = yes
sqltrace = no
sqltracefile = ${logdir}/sqltrace.sql
num_sql_socks = 5
connect_failure_retry_delay = 60
lifetime = 0
max_queries = 0
nas_table = "nas"
$INCLUDE ${db_dir}/sql/mssql/dialup.conf
}
Mysql数据库配置
创建表
CREATE TABLE radacct (
radacctid bigint(21) NOT NULL auto_increment,
acctsessionid varchar(64) NOT NULL default '',
acctuniqueid varchar(32) NOT NULL default '',
username varchar(64) NOT NULL default '',
groupname varchar(64) NOT NULL default '',
realm varchar(64) default '',
nasipaddress varchar(15) NOT NULL default '',
nasportid varchar(15) default NULL,
nasporttype varchar(32) default NULL,
acctstarttime datetime NULL default NULL,
acctstoptime datetime NULL default NULL,
acctsessiontime int(12) default NULL,
acctauthentic varchar(32) default NULL,
connectinfo_start varchar(50) default NULL,
connectinfo_stop varchar(50) default NULL,
acctinputoctets bigint(20) default NULL,
acctoutputoctets bigint(20) default NULL,
calledstationid varchar(50) NOT NULL default '',
callingstationid varchar(50) NOT NULL default '',
acctterminatecause varchar(32) NOT NULL default '',
servicetype varchar(32) default NULL,
framedprotocol varchar(32) default NULL,
framedipaddress varchar(15) NOT NULL default '',
acctstartdelay int(12) default NULL,
acctstopdelay int(12) default NULL,
xascendsessionsvrkey varchar(10) default NULL,
PRIMARY KEY (radacctid),
UNIQUE KEY acctuniqueid (acctuniqueid),
KEY username (username),
KEY framedipaddress (framedipaddress),
KEY acctsessionid (acctsessionid),
KEY acctsessiontime (acctsessiontime),
KEY acctstarttime (acctstarttime),
KEY acctstoptime (acctstoptime),
KEY nasipaddress (nasipaddress)
) ENGINE = INNODB;
CREATE TABLE radcheck (
id int(11) unsigned NOT NULL auto_increment,
username varchar(64) NOT NULL default '',
attribute varchar(64) NOT NULL default '',
op char(2) NOT NULL DEFAULT '==',
value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY username (username(32))
) ;
CREATE TABLE radgroupcheck (
id int(11) unsigned NOT NULL auto_increment,
groupname varchar(64) NOT NULL default '',
attribute varchar(64) NOT NULL default '',
op char(2) NOT NULL DEFAULT '==',
value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY groupname (groupname(32))
) ;
CREATE TABLE radgroupreply (
id int(11) unsigned NOT NULL auto_increment,
groupname varchar(64) NOT NULL default '',
attribute varchar(64) NOT NULL default '',
op char(2) NOT NULL DEFAULT '=',
value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY groupname (groupname(32))
) ;
CREATE TABLE radreply (
id int(11) unsigned NOT NULL auto_increment,
username varchar(64) NOT NULL default '',
attribute varchar(64) NOT NULL default '',
op char(2) NOT NULL DEFAULT '=',
value varchar(253) NOT NULL default '',
PRIMARY KEY (id),
KEY username (username(32))
) ;
CREATE TABLE radusergroup (
username varchar(64) NOT NULL default '',
groupname varchar(64) NOT NULL default '',
priority int(11) NOT NULL default '1',
KEY username (username(32))
) ;
CREATE TABLE radpostauth (
id int(11) NOT NULL auto_increment,
username varchar(64) NOT NULL default '',
pass varchar(64) NOT NULL default '',
reply varchar(32) NOT NULL default '',
authdate timestamp NOT NULL,
PRIMARY KEY (id)
) ENGINE = INNODB;
CREATE TABLE nas (
id int(10) NOT NULL auto_increment,
nasname varchar(128) NOT NULL,
shortname varchar(32),
type varchar(30) DEFAULT 'other',
ports int(5),
secret varchar(60) DEFAULT 'secret' NOT NULL,
server varchar(64),
community varchar(50),
description varchar(200) DEFAULT 'RADIUS Client',
PRIMARY KEY (id),
KEY nasname (nasname)
);
创建用户
-- 创建用户 --
CREATE USER 'radius'@'%';
-- 设置密码 --
SET PASSWORD FOR 'radius'@'%' = PASSWORD('123456');
-- 为用户授予radius数据库的权限 --
GRANT ALL ON radius.* TO 'radius'@'%';
-- 加入认证数据 --
INSERT INTO `radcheck` VALUES ('1', 'zyt@siganet', 'Cleartext-Password', ':=', 'siganet');
测试
测试说明
使用portal服务器设置账户密码向AC推送认证消息,AC会向FreeRadius请求认证,若通过,则证明认证成功。
测试步骤
- 手机连接测试WIFI
- 启动FreeRadius服务器
- 运行测试代码
- 查看手机联网状态
若手机联网成功,则表示认证成功
测试代码
public static void main(String[] args) {
ChapAuthTest();
}
/**
* 上线请求测试
*/
public static void ChapAuthTest() {
new SkspruceChapAuth("192.168.1.199", 2000, "192.168.1.200", "zyt@siganet", "siganet", Utils.getRandom(65025, 0)).start();
}
SkspruceChapAuth.java
package tlv.socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import tlv.bean.Attr;
import tlv.bean.TlvHwBean;
import tlv.enums.TlvType;
import tlv.tools.TlvSkspruce;
/**
* 西加云杉700E设备认证
* @author yet
*
*/
public class SkspruceChapAuth extends Thread {
private DatagramSocket s;
private InetAddress hostAddress;
private byte[] buf = new byte[1000];
private DatagramPacket dp = new DatagramPacket(buf, buf.length);
private byte[] bufRe = new byte[1000];
private DatagramPacket dpRe = new DatagramPacket(bufRe, bufRe.length);
private int port;
private String userIp;
private int serialNo;
private String username;
private String password;
public void run() {
try {
s.send(Dgram.toDatagram(ReqChallenge(), hostAddress, port));
s.receive(dp);
TlvHwBean b = parse(dp.getData());
if(b.getErrCode()==0){
System.out.println("获取Challenge成功");
System.out.println("开始发送认证");
s.send(Dgram.toDatagram(ReqAuth(b.getReqId()), hostAddress, port));
s.receive(dpRe);
TlvHwBean bre = parse(dpRe.getData());
if(bre.getErrCode()==0){
System.out.println("用户认证成功");
}else{
System.out.println("用户认证失败");
}
}else{
System.out.println("获取Challenge失败");
}
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
/**
* 生成Challenge的请求
* @return
*/
public byte[] ReqChallenge() {
List<Attr> attr = new ArrayList<Attr>();
Attr a = new Attr(1, username.getBytes());
Attr b = new Attr(2, password.getBytes());
attr.add(a);
attr.add(b);
return TlvSkspruce.buildSkspruce(TlvType.ReqChallenge,serialNo,0, userIp, attr);
}
/**
* 生成认证请求
* @param reqId
* @return
*/
private byte[] ReqAuth(int reqId){
List<Attr> attr = new ArrayList<Attr>();
Attr a = new Attr(1, username.getBytes());
Attr b = new Attr(2, password.getBytes());
attr.add(a);
attr.add(b);
return TlvSkspruce.buildSkspruce(TlvType.ReqAuth,serialNo, reqId, userIp, attr);
}
/**
* 将byte[]转为TlvHwBean
* @param a
* @return
*/
private TlvHwBean parse(byte[] a){
return TlvSkspruce.parseHw(a);
}
/**
* @param ip AC的ip地址
* @param port AC监听的端口
* @param userIp 用户内网ip
* @param username 用户名
* @param password 密码
* @param serialNo 一段时间内唯一的序列号
*/
public SkspruceChapAuth(String ip, int port,String userIp,String username,String password,int serialNo) {
this.port = port;
this.userIp = userIp;
this.serialNo = serialNo;
this.username = username;
this.password = password;
try {
s = new DatagramSocket();
hostAddress = InetAddress.getByName(ip);
} catch (UnknownHostException e) {
System.err.println("Cannot find host");
System.exit(1);
} catch (SocketException e) {
System.err.println("Can't open socket");
e.printStackTrace();
System.exit(1);
}
System.out.println("请求开始");
}
}