Kea DHCP Hooks开发

目录

摘要
开发环境要求
Hook开发需求
Hook代码编写
Hook代码编译
Hook Kea配置
总结
参考文献
附录

摘要

简单Kea DHCP开发案例教程。通过本篇文章使读者能够对Hook开发有一个大致轮廓。主要侧重操作,对于概念的说明请查看官网。申明:本篇使用的是官方文档案例

开发环境要求

  1. Ubuntu
  2. gcc编译环境 apt install gcc
  3. vim编辑器
  4. Kea相关Hook开发库(安装Kea即可)

Hook开发需求

Kea DHCPv4用于分配IPv4地址给客户端(也会传给客户端其他信息,比如DNS服务器地址)。假设需要根据客户硬件地址和客户请求IPv4地址进行分类,且记录感兴趣的客户端硬件地址和已分配IP地址。

Hook代码编写

  • version - Hook代码被编译时Kea代码使用的版本
  • load - 当Hook被服务器加载时调用
  • unload - 当Hook被服务器卸载是调用

version函数

用于检查Hook是否兼容当前正在运行的Kea服务器。

源码
// version.cc

#include <hooks/hooks.h>

extern "C" {
    int version() {
        return (KEA_HOOKS_VERSION);
    }
}

load和unload函数

  1. load肯定被调用,unload不一定被调用,比如系统异常关闭。
  2. 这两个函数主要用于资源的分配和关闭。
  3. load函数可以注册自定义callout名字,比如如下代码:
int load(LibraryHandle& libhandle) {
    // Register the callouts on the hooks. We assume that a header file declares the "classify" and "write_data" functions.
    libhandle.registerCallout("pkt4_receive", classify);
    libhandle.registerCallout("pkt4_send", write_data);
    // Open the log file
    interesting.open("/tmp/interesting.log", std::fstream::out | std::fstream::app);
    return (interesting ? 0 : 1);
}
源码
  1. 将创建两个文件,分别为library_common.h和load_unload.cc,library_common.h用于文件处理器声明。load_unload.cc用于定义load和unload函数。
// library_common.h
#ifndef LIBRARY_COMMON_H
#define LIBRARY_COMMON_H
#include <fstream>
// 日志文件处理器声明
extern std::fstream interesting;
#endif // LIBRARY_COMMON_H
  1. 定义load和unload函数源文件。==interesting.open的文件必须保证文件夹是存在的==,否则加载会失败
// load_unload.cc
#include <hooks/hooks.h>
#include "library_common.h"

using namespace isc::hooks;

// 日志文件处理器定义
std::fstream interesting;

extern "C" {
    int load(LibraryHandle&) {
        interesting.open("/tmp/interesting.log",std::fstream::out | std::fstream::app);

        return (interesting ? 0 : 1);
    }

    int unload() {
        if (interesting) {
            interesting.close();
        }

        return (0);
    }
}

Callout函数

这里的Callout是所有Hook point的统称。并不是真的叫callout这个名字。

callout签名

返回0表示成功,非0表示失败。

extern "C" {
    int callout(CalloutHandle& handle);
}
callout参数

CalloutHandle对象提供2个方法getArgument和setArgument,获取和设置参数。下面的举例如何使用

// 服务端代码片段,演示设置参数
int count = 10;
boost::shared_ptr<Pkt4> pktptr = ... // Set to appropriate value
// 假设handle对象已经创建
handle.setArgument("data_count", count);
handle.setArgument("inpacket", pktptr);
// 调用 callouts
...
// 获取修改的值
handle.getArgument("data_count", count);
handle.getArgument("inpacket", pktptr);
源码
// pkt4_receive.cc
#include <hooks/hooks.h>
#include <dhcp/pkt4.h>
#include "library_common.h"
#include <string>

using namespace isc::dhcp;
using namespace isc::hooks;
using namespace std;

extern "C" {
// 在pkt4_receive时调用该函数
int pkt4_receive(CalloutHandle& handle) {
    // A pointer to the packet is passed to the callout via a "boost" smart
    // pointer. The include file "pkt4.h" typedefs a pointer to the Pkt4
    // object as Pkt4Ptr.  Retrieve a pointer to the object.
    Pkt4Ptr query4_ptr;
    handle.getArgument("query4", query4_ptr);

    // Point to the hardware address.
    HWAddrPtr hwaddr_ptr = query4_ptr->getHWAddr();

    // The hardware address is held in a public member variable. We'll classify
    // it as interesting if the sum of all the bytes in it is divisible by 4.
    //  (This is a contrived example after all!)
    long sum = 0;
    for (int i = 0; i < hwaddr_ptr->hwaddr_.size(); ++i) {
        sum += hwaddr_ptr->hwaddr_[i];
    }

    // Classify it.
    if (sum % 4 == 0) {
        // Store the text form of the hardware address in the context to pass
        // to the next callout.
        string hwaddr = hwaddr_ptr->toText();
        handle.setContext("hwaddr", hwaddr);
    }
    return (0);
};
}
// pkt4_send.cc
#include <hooks/hooks.h>
#include <dhcp/pkt4.h>
#include "library_common.h"
#include <string>

using namespace isc::dhcp;
using namespace isc::hooks;
using namespace std;

extern "C" {
// 在pkt4_send hook的时候调用
int pkt4_send(CalloutHandle& handle) {
    // Obtain the hardware address of the "interesting" client.  We have to
    // use a try...catch block here because if the client was not interesting,
    // no information would be set and getArgument would thrown an exception.
    string hwaddr;
    try {
        handle.getContext("hwaddr", hwaddr);

        // getContext didn't throw so the client is interesting.  Get a pointer
        // to the reply.
        Pkt4Ptr response4_ptr;
        handle.getArgument("response4", response4_ptr);

        // Get the string form of the IP address.
        string ipaddr = response4_ptr->getYiaddr().toText();

        // Write the information to the log file.
        interesting << hwaddr << " " << ipaddr << "\n";

        // ... and to guard against a crash, we'll flush the output stream.
        flush(interesting);


    } catch (const NoSuchCalloutContext&) {
        // No such element in the per-request context with the name "hwaddr".
        // This means that the request was not an interesting, so do nothing
        // and dismiss the exception.
     }
    return (0);
}
}

Hook代码编译

根据上面的操作,完整的文件列表如下:

source-code-list

编译
g++ -I <install-dir>/include/kea -L <install-dir>/lib -fpic -shared -o example.so load_unload.cc pkt4_receive.cc pkt4_send.cc version.cc -lkea-dhcpsrv -lkea-dhcp++ -lkea-hooks -lkea-log -lkea-util -lkea-exceptions

上面编译成功后会在编译目录下,看到 example.so

指向kea安装时的目录,除非你安装时指定–prefix,否则默认为/usr/local

选项解释
-I指定额外的头文件搜索路径DIRECTORY。
-L指定额外的函数库搜索路径DIRECTORY
-fpic表明使用地址无关代码,PIC:Position Independent Code.
-shared生成共享目标文件
-o指定生成库的名字
-l连接时搜索指定的函数库LIBRARY

Hook Kea配置

复制

复制Hook库到/usr/local/lib/hooks/下(根据你的喜好你可以放置在任意位置)

编辑

编辑vim /usr/local/etc/kea/kea-dhcp4.conf,在文件的Dhcp4节点下添加如下配置

"hooks-libraries": [{
    "library" : "/usr/local/lib/hooks/example.so"
}]

重启

重启后,运行测试工具,成功的话可以在/tmp/interesting.log目录如下输出:

filter_result

总结

Kea如何测试测试,请查阅Karaf教程之Config Admin服务的使用

参考文献

Hooks Developer’s Guide

Hooks Libraries

Linux共享对象之编译参数fPIC


myqrcode

附录

源码附件

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kea DHCP(Dynamic Host Configuration Protocol)是一个灵活且高度可扩展的DHCP服务器软件,它由IETF (Internet Engineering Task Force) 委员会开发,用于自动分配IP地址和网络配置给网络中的设备。Kea DHCP的主要优点和缺点如下: **优点:** 1. **可定制性和灵活性**:Kea提供了强大的插件系统,可以根据需求自定义功能,支持IPv4和IPv6地址分配。 2. **安全性**:内置安全机制,如租约保护、身份验证和授权,有助于防止恶意攻击和未经授权的配置。 3. **高可靠性**:模块化设计使得故障排查和维护更方便,且支持高可用性和集群部署。 4. **审计与日志**:支持详细的审计和日志记录,便于跟踪网络活动和事件。 5. **易扩展**:能够处理大规模网络和动态变化的需求。 **缺点:** 1. **学习曲线陡峭**:Kea的功能强大,对于新手来说可能有一定的学习成本,特别是配置复杂场景。 2. **资源消耗**:对于大型网络,管理和维护这样一个复杂的系统可能会占用较多的服务器资源。 3. **性能开销**:尽管可扩展,但处理大量请求时,性能可能不如一些专为简化部署而优化的传统DHCP服务器。 4. **依赖于IETF标准**:这意味着某些新功能或优化可能需要等待标准化过程完成,导致更新周期可能较长。 5. **社区和文档**:虽然Kea社区活跃,但对于某些用户来说,文档和教程可能不够全面,尤其是在早期版本中。 **相关问题--:** 1. Kea如何处理IPv6地址分配? 2. 如何在Kea中启用身份验证? 3. Kea的模块化设计如何影响其性能?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值