openwrt wifidog是我linux c语言编程的启蒙项目,一年前折腾此项目大半年,从此爱上了linux 系统编程。现在看来,这是一个再简单不过的linux c语言项目了。在此以wifidog官方源码作为实例分析,不过实际推荐用apfree_wifidog,使用epoll、libevent等新技术,并且是国人在维护的项目。
wifidog 认证主要通过iptables命令实现网络规则制定,端口跳转认证,为此一定要先熟悉iptables命令原理(扩展参考tc/netfilter/libpcap等知识)。了解iptables基础知识后再查看官方的流程图(实在太陈旧):
wifidog_wiki_help.png Download (11.1 KB) - added by Frederic Sheedy 9 years ago. "I have questions or I need help icon"
wifidog_wiki_contribute.png Download (11.3 KB) - added by Frederic Sheedy 9 years ago. "I want to contribute to Wifidog icon"
src/fw_iptables.c
核心代码片段:
iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port);
case FW_ACCESS_ALLOW:
iptables_do_command("-t mangle -A " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip,
mac, tag);
rc = iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j ACCEPT", ip);
break;
2060端口监听服务程序,为libhttpd文件夹下的文件,将编译成libhttpd.so库,提供API文件libhttpd/httpd.h。这是一个非常简单的http协议解析 server。
在src/gateway.c
main函数初始化时,调用此server如下:
httpdAddCContent(webserver, "/", "wifidog", 0, NULL, http_callback_wifidog);
httpdAddCContent(webserver, "/wifidog", "", 0, NULL, http_callback_wifidog);
httpdAddCContent(webserver, "/wifidog", "about", 0, NULL, http_callback_about);
httpdAddCContent(webserver, "/wifidog", "status", 0, NULL, http_callback_status);
httpdAddCContent(webserver, "/wifidog", "auth", 0, NULL, http_callback_auth);
httpdAddCContent(webserver, "/wifidog", "disconnect", 0, NULL, http_callback_disconnect);
httpdSetErrorFunction(webserver, 404, http_callback_404);
回调函数都定义在src/http.c中。
for (rule = get_ruleset("global"); rule != NULL; rule = rule->next) {
...
fw_allow_host(r->request.host);
...
}
src/auth.c
中: auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, client->ip, client->mac, token, 0, 0, 0, 0);
wifidog一旦接收到认证服务器回复AUTH_ALLOWED
,就是简单回复几个字符串Auth: 1
,则立即执行上述的iptables命令放行。
if ((tmp = strstr(res, "Auth: "))) {
if (sscanf(tmp, "Auth: %d", (int *)&authresponse->authcode) == 1) {
debug(LOG_INFO, "Auth server returned authentication code %d", authresponse->authcode);
free(res);
return (authresponse->authcode);
} else {
debug(LOG_WARNING, "Auth server did not return expected authentication code");
free(res);
return (AUTH_ERROR);
}
}
至此,wifidog基本功能实现过程已经完毕,后面再补充其他功能详解。