西加云杉700E设备AAA认证之Radius服务器与Mysql数据库交互

简介

目的: 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("请求开始");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂小海豹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值