linuxwifi源代码,Linux⽆线认证----wifidog源码分析
wifidog
wifidog开源模块,通过iptable对报⽂进⾏重定向到端⼝2060接⼝,对报⽂进⾏拦截,利⽤iptable实现⽤户上⽹⾏为管理功能,⽬前市⾯上的⽆线多采⽤此模块进⾏portale认真。 本⽂章对wifidog的源码进⾏了分析,希望有所帮助。
1 main
1.1 config_init();初始化全局变量,设置默认值
1.2 parse_commandline(argc,
argv);读取命令⾏参数
(1). -h 打印命令参数信息;
(2). -c 指定使⽤的wifidog配置⽂件;
(3). -f  wifidog前台运⾏;
linux创建新用户和密码
(4). -d 设置调试等级;
(5). -s  将⽇志信息输⼊到log⽇志;
(6). -w 与Wdctl通信域socket路径;
(7). -v  打印wifidog版本信息;
(8). -x  ⽗进程id;
(9).  -i  Internal socket path used when re-starting self.;
(10). -a  Path to /proc/net/arp replacement - mainly useful for debugging.;
(11) -p    Save pid to file;
1.3 config_read(config->configfile);读取f⽂件,并将其内容保存到全局变量
1.4 config_validate();检验是否配置gatewayinterface和authserver
1.5client_list_init();初始化client链表
1.6 init_signals();初始化信号
1.7 append_x_restartargv(),保存传⼊参数和进程id。
1.8 执⾏main_loop循环
2 main_loop循环
2.1 设置wifidog启动时间started_time
2.2 存放进程id到指定⽂件save_pid_file(config->pidfile);
2.3 获取gateway的ip地址config->gw_address
2.4 获取gateway id即mac地址config->gw_id
2.5 调⽤函数httpdCreate()创建web server(建⽴tcp,socket监听默认端⼝2060)
2.6 函数register_fd_cleanup_on_fork(webserver->serverSock);初始化socket表
2.7 web 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);
2.8 清空防⽕墙规则fw_destroy();
2.9 初始化防⽕墙规则fw_init();
2.10 创建线程,检测client超时;thread_client_timeout_check
2.11 创建线程,处理wdctl发送的控制信息;thread_wdctl
2.12 创建线程,检测认证server是否在线;thread_ping
2.13 进⼊while循环;获取client连接,为每个client创建线程,处理http请求.
2.1 fw_init()
2.1.1 在mangle表创建新的链表和规则
1).在mangle表中创建新的链表。
("-t mangle -N " CHAIN_TRUSTED);
("-t mangle -N " CHAIN_OUTGOING);
("-t mangle -N " CHAIN_INCOMING);
("-t mangle -N " CHAIN_AUTH_IS_DOWN);
2).在挂载点为PREROUTING ,输⼊接⼝为gw_interface,执⾏相应的链表。
("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_OUTGOING, config->gw_interface);
("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_TRUSTED, config->gw_interface);
("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_AUTH_IS_DOWN, config->gw_interface);
3).在挂载点为POSTROUTING  ,输出接⼝为gw_interface,执⾏相应的链表。
("-t mangle -I POSTROUTING 1 -o %s -j " CHAIN_INCOMING, config->gw_interface);
4).链表CHAIN_TRUSTED,匹配mac地址为⽩名单中设置的mac,则设置mark标记为FW_MARK_KNOWN = 2,对此mac不进⾏拦截。
("-t mangle -A " CHAIN_TRUSTED " -m mac --mac-source %s -j MARK --set-mark %d", p->mac,FW_MARK_KNOWN);
2.1.2 在nat表中创建新的链表和规则
1). 在nat表中创建新的链表。
("-t nat -N " CHAIN_OUTGOING);
("-t nat -N " CHAIN_TO_ROUTER);
("-t nat -N " CHAIN_TO_INTERNET);
("-t nat -N " CHAIN_GLOBAL);
("-t nat -N " CHAIN_AUTHSERVERS);
("-t nat -N " CHAIN_AUTH_IS_DOWN);
2).在挂载点PREROUTING,输⼊接⼝gw_interface,执⾏表CHAIN_OUTGOING
("-t nat -A PREROUTING -i %s -j " CHAIN_OUTGOING, config->gw_interface);
3).在链表CHAIN_OUTGOING,⽬的地址为gw_address,则执⾏链表 CHAIN_TO_ROUTER。
("-t nat -A " CHAIN_OUTGOING " -d %s -j " CHAIN_TO_ROUTER, config->gw_address);
("-t nat -A " CHAIN_TO_ROUTER " -j ACCEPT");
4).在链表CHAIN_OUTGOING,执⾏表CHAIN_TO_INTERNET。
("-t nat -A " CHAIN_OUTGOING " -j " CHAIN_TO_INTERNET);
5).表CHAIN_TO_INTERNET添加规则,tcp协议,⽬的端⼝80,匹配mark标记,并重定向到端⼝proxy_port.
("-t nat -A " CHAIN_TO_INTERNET" -p tcp --dport 80 -m mark --mark 0x%u -j REDIRECT --to-port
%u",FW_MARK_KNOWN, proxy_port);
("-t nat -A " CHAIN_TO_INTERNET " -p tcp --dport 80 -m mark --mark 0x%u -j REDIRECT --to-port
%u",FW_MARK_PROBATION, proxy_port);
6).表CHAIN_TO_INTERNET添加规则,匹配mark标记,返回ACCEPT.
("-t nat -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_KNOWN);
("-t nat -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_PROBATION);
7).在链表CHAIN_TO_INTERNET,执⾏表CHAIN_UNKNOWN。
iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -j " CHAIN_UNKNOWN);
8).在链表CHAIN_UNKNOWN,执⾏表CHAIN_AUTHSERVERS、CHAIN_GLOBAL、CHAIN_AUTH_IS_DOWN。("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_AUTHSERVERS);
("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_GLOBAL);
("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_AUTH_IS_DOWN);
9). 在链表CHAIN_AUTH_IS_DOWN,添加规则,匹配mark标记,返回ACCEPT
("-t nat -A " CHAIN_AUTH_IS_DOWN " -m mark --mark 0x%u  -j ACCEPT",
FW_MARK_AUTH_IS_DOWN);
10). 在链表CHAIN_UNKNOWN,添加规则,tcp协议,⽬的端⼝80,重定向到端⼝gw_port。
("-t nat -A " CHAIN_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port);
2.1.3 在fliter表中创建新的链表和规则
1). 在flitert表中创建新的链表
("-t filter -N " CHAIN_TO_INTERNET);
("-t filter -N " CHAIN_AUTHSERVERS);
("-t filter -N " CHAIN_LOCKED);
("-t filter -N " CHAIN_GLOBAL);
("-t filter -N " CHAIN_KNOWN);
("-t filter -N " CHAIN_UNKNOWN);
("-t filter -N " CHAIN_AUTH_IS_DOWN);
2). filter表中在forword挂载点,输⼊接⼝config->gw_interface,执⾏链表CHAIN_TO_INTERNET
("-t filter -I FORWARD -i %s -j " CHAIN_TO_INTERNET, config->gw_interface);
3). filter中添加链表CHAIN_TO_INTERNET,匹配状态INVALID,则DROP
("-t filter -A " CHAIN_TO_INTERNET " -m state --state INVALID -j DROP");
4). 在链表中CHAIN_TO_INTERNET添加规则,输出⼝ext_interface, tcp协议,则执⾏TCPMSS ,--clamp-mss-to-pmtu根据mtu调整MSS的值
("-t filter -A " CHAIN_TO_INTERNET " -o %s -p tcp --tcp-flags SYN,RST SYN
-j TCPMSS --clamp-mss-to-pmtu", ext_interface);
5). 在链表CHAIN_TO_INTERNET添加规则CHAIN_AUTHSERVERS,对于⽬的ip为authserverip地址的报⽂放⾏
("-t filter -A " CHAIN_TO_INTERNET " -j " CHAIN_AUTHSERVERS);
iptables_fw_set_authservers();
6). 从配置⽂件中读取相应的规则,并配置防⽕墙
iptables_load_ruleset
2.2 while循环;获取client连接,为每个client创建线程,处理http请求.
2.2.1. 获取client连接 r = httpdGetConnection(webserver, NULL);
2.2.2. 为每个client创建线程,处理http请求;thread_httpd
2.2.1 thread_httpd
1). 读取http请求httpdReadRequest();
2). 查访问⽬录,如果dir= NULL,则调⽤函数http_callback_404
dir = _httpd_findContentDir(server, dirName, HTTP_FALSE);
3). 根据dir和entryName查entry路径
entry = _httpd_findContentEntry(r, dir, entryName);
4).调⽤注册的entry函数
(entry->function) (server, r);
即:
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);
2.2.1.1 http_callback_404
1). 检测⽹络是否连接,否,则返回提⽰页⾯
send_http_page(r, "Uh oh! Internet access unavailable!", buf);
2). 检测认证server是否在线,否,则返回提⽰页⾯
send_http_page(r, "Uh oh! Login screen unavailable!", buf);
3).检测域名⽩名单,存在,放⾏!
get_ruleset("global");
fw_allow_host(r->request.host);
4). 返回302重定向报⽂
http_send_redirect_to_auth(r, urlFragment, "Redirect to login page");
2.2.1.2 http_callback_auth
当client接收到302重定向报⽂后,访问认证server,并返回认证界⾯, 输⼊⽤户名密码后,向authserver返回,并获取到authserver为它分配的token值,执⾏redirect url跳转,向wifidog模块发送auth报⽂,携带token值,请求认证。
1.向client链表中添加client信息
client_list_add(r->clientAddr, mac, token->value);
2.对client进⾏认证处理
authenticate_client(r);
1). 获取token值;
httpdGetVariableByName(r, "token"))
2). 向认证服务器发送认证请求
auth_server_request();
3). 根据认证结果,放⾏或拦截client
fw_allow(client, FW_MARK_PROBATION);
fw_deny(client);
2.3 thread_ping
函数ping(void)
1). 建⽴tcp连接
2). 发送ping包
res = https_get(sockfd, request, auth_server->authserv_hostname);
res = http_get(sockfd, request);
3)标记认证服务器状态,如果服务器down,设置防⽕墙规则,放⾏所有client。
fw_set_authdown();
fw_set_authup();

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。