上一篇分析了接入设备的首次浏览器访问请求如何通过 防火墙过滤规则 重定向到 wifidog 的 HTTP 服务中,本篇主要分析了 wifidog 在接收到 接入设备的 HTTP 访问请求后,如何将此 HTTP 请求重定向到 认证服务器(auth-server) 上。


通过上面的防火墙规则,会将通过上面的防火墙规则,会将HTTP请求的外部IP地址和端口通过NAT方式重定向至本地wifidog内嵌HTTP服务器的地址和端口上,并由内嵌HTTP服务器进行服务,而内嵌HTTP服务器的路径和回调处理如下:


[cpp]view plaincopy
  1. if((webserver=httpdCreate(config->gw_address,config->gw_port))==NULL){
  2. debug(LOG_ERR,"Couldnotcreatewebserver:%s",strerror(errno));
  3. exit(1);
  4. }
  5. debug(LOG_DEBUG,"Assigningcallbackstowebserver");
  6. httpdAddCContent(webserver,"/","wifidog",0,NULL,http_callback_wifidog);
  7. httpdAddCContent(webserver,"/wifidog","",0,NULL,http_callback_wifidog);
  8. httpdAddCContent(webserver,"/wifidog","about",0,NULL,http_callback_about);
  9. httpdAddCContent(webserver,"/wifidog","status",0,NULL,http_callback_status);
  10. httpdAddCContent(webserver,"/wifidog","auth",0,NULL,http_callback_auth);
  11. httpdAddC404Content(webserver,http_callback_404);

客户端首次访问时回调 客户端首次访问时回调http_callback_404函数,在该函数中根据获取的客户端信息来配置重定向的URL fragment,如下:

[cpp]view plaincopy
  1. void
  2. http_callback_404(httpd*webserver,request*r)
  3. {
  4. chartmp_url[MAX_BUF],
  5. *url,
  6. *mac;
  7. s_config*config=config_get_config();
  8. t_auth_serv*auth_server=get_auth_server();
  9. memset(tmp_url,0,sizeof(tmp_url));
  10. /*
  11. *XXXNotethecodebelowassumesthattheclient'srequestisaplain
  12. *httprequesttoastandardport.Atanyrate,thishandleriscalledonly
  13. *iftheinternet/authserverisdownsoit'snotahugeloss,butstill.
  14. *//*用户需要访问的URL*/
  15. snprintf(tmp_url,(sizeof(tmp_url)-1),"http://%s%s%s%s",
  16. r->request.host,
  17. r->request.path,
  18. r->request.query[0]?"?":"",
  19. r->request.query);
  20. url=httpdUrlEncode(tmp_url);
  21. if(!is_online()){
  22. /*路由器都接入不到internet*/
  23. char*buf;
  24. send_http_page(r,"Uhoh!Internetaccessunavailable!",buf);
  25. free(buf);
  26. }
  27. elseif(!is_auth_online()){
  28. /*authserver挂起*/
  29. char*buf;
  30. send_http_page(r,"Uhoh!Loginscreenunavailable!",buf);
  31. free(buf);
  32. }
  33. else{
  34. /*配置重定向到authserver的url参数*/
  35. char*urlFragment;
  36. if(!(mac=arp_get(r->clientAddr))){
  37. /*WecouldnotgettheirMACaddress*/
  38. debug(LOG_INFO,"FailedtoretrieveMACaddressforip%s,sonotputtingintheloginrequest",r->clientAddr);
  39. safe_asprintf(&urlFragment,"%sgw_address=%s&gw_port=%d&gw_id=%s&url=%s",
  40. auth_server->authserv_login_script_path_fragment,
  41. config->gw_address,
  42. config->gw_port,
  43. config->gw_id,
  44. url);
  45. }else{
  46. debug(LOG_INFO,"GotclientMACaddressforip%s:%s",r->clientAddr,mac);
  47. safe_asprintf(&urlFragment,"%sgw_address=%s&gw_port=%d&gw_id=%s&mac=%s&url=%s",
  48. auth_server->authserv_login_script_path_fragment,
  49. config->gw_address,
  50. config->gw_port,
  51. config->gw_id,
  52. mac,
  53. url);
  54. }
  55. /*调用该函数将用户请求重定向到authserver的登录页面*/
  56. http_send_redirect_to_auth(r,urlFragment,"Redirecttologinpage");
  57. free(urlFragment);
  58. }
  59. free(url);
  60. }

上面代码基本不用解释,具体重定向至auth server的消息在下面的 http_send_redirect_to_auth 函数中实现:

[cpp]view plaincopy
  1. voidhttp_send_redirect_to_auth(request*r,char*urlFragment,char*text)
  2. {
  3. char*protocol=NULL;
  4. intport=80;
  5. t_auth_serv*auth_server=get_auth_server();
  6. if(auth_server->authserv_use_ssl){
  7. protocol="https";
  8. port=auth_server->authserv_ssl_port;
  9. }else{
  10. protocol="http";
  11. port=auth_server->authserv_http_port;
  12. }
  13. char*url=NULL;
  14. safe_asprintf(&url,"%s://%s:%d%s%s",
  15. protocol,
  16. auth_server->authserv_hostname,
  17. port,
  18. auth_server->authserv_path,
  19. urlFragment
  20. );
  21. http_send_redirect(r,url,text);
  22. free(url);
  23. }

具体的重定向URL给个实例:


POST /login/?gw_address=192.168.1.1&gw_port=2060&gw_id=default&mac=44:94:fc:ef:28:40&url=http%3A//www.baidu.com/ HTTP/1.1


可以看到这里有这几个参数信息:


2gw_address,路由器的LAN地址

2gw_port:为wifidog的监听端口

2gw_id:路由器的标识名

2mac:客户端设备的MAC地址

2url:为客户端访问的原URL(以便于重定向)

更多相关文章

  1. linux socket网络编程:fcntl select(多个客户端连接服务器端情形)
  2. 浅谈Oracle函数返回Table集合
  3. Linux-C语言函数手册
  4. Linux 下nice 函数用法提高一个进程的友善值
  5. 设置查看linux 造成程序Core dumped 的函数调用层次
  6. 为什么函数在ELF中的其他共享库的长度信息?
  7. Linux内核中的container_of函数简要介绍
  8. Linux环境下注册函数的调用顺序
  9. Linux网络编程-客户端与服务器端通信(Echo)

随机推荐

  1. Android控件属性手册
  2. Android users-permission权限列表
  3. Android之使用ContentResolver对通信录中
  4. Android单例模式
  5. android:repeatCount="infinite"在set中
  6. Android(安卓)Display架构分析--侧重高通
  7. Android--Activity篇之启动模式
  8. android断点下载器案例
  9. [转]Android(安卓)Music和第三方应用
  10. Android之如何解决Android studio运行出