iptables / cherrypy 重定向更改请求 mid-processing
iptables / cherrypy redirection changes request mid-processing
抱歉,标题含糊不清,但我的问题解释起来有点复杂。
我在 cherrypy 中为 WLAN 接入点写了一个 "captive portal",它只是一个服务器,在地址在特定页面注册之前阻止 MAC 地址访问互联网。为此,我写了一些 iptables 规则,将所有 HTTP 流量重定向到我
sudo iptables -t mangle -N internet
sudo iptables -t mangle -A PREROUTING -i $DEV_IN -p tcp -m tcp --dport 80 -j internet
sudo iptables -t mangle -A internet -j MARK --set-mark 99
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -m mark --mark 99 -m tcp --dport 80 -j DNAT --to-destination 10.0.0.1
(此设置的细节对我的问题来说并不重要,只需注意创建了一个 "internet" 链,它将 HTTP 重定向到接入点上的端口 80)
在 AP 的 80 端口,cherrypy 服务器提供一个带有 "register" 按钮的静态登陆页面,该按钮向 http://10.0.0.1/agree 发出 POST 请求。为了处理这个请求,我创建了一个这样的方法:
@cherrypy.expose
def agree(self, **kwargs):
#retrieve MAC address of client by checking ARP table
ip = cherrypy.request.remote.ip
mac = str(os.popen("arp -a " + str(ip) + " | awk '{ print }' ").read())
mac = mac.rstrip('\r\n')
#add an iptables rule to whitelist the client, rmtrack to remove previous connection information
os.popen("sudo iptables -I internet 1 -t mangle -m mac --mac-source %s -j RETURN" %mac)
os.popen("sudo rmtrack %s" %ip)
return open('welcome.html')
因此此方法从 arp table 中检索客户端的 MAC 地址,然后添加一个 iptables 异常以从 "internet" 将流量重定向到门户的链。
现在,当我测试此设置时,发生了一些有趣的事情。在 iptables 中添加例外是有效的——即客户端现在可以访问网页而无需重定向到我。问题是 初始请求 没有到达我的服务器,即页面 welcome.html
从未打开 - 相反,在 iptables 之后并执行 rmtrack 调用时,客户端尝试在重定向到我的门户之前在他们请求的页面上打开 "agree" 路径。
例如,如果他们在地址栏中点击 "google.com",然后被发送到我的门户并同意,他们现在会尝试打开 http://google.com/agree。结果,他们在一段时间后得到一个错误。似乎 iptables 或 rmtrack 调用将请求更改为去往原始目的地 而 它仍在我的服务器上处理,这不会产生任何影响对我来说有意义。因此,在发出这些终端命令后,我 return 是哪个静态页面或进行了哪些重定向都无关紧要 - 客户端未使用我函数的 return 值。
我该如何解决这个问题?感谢每一条有用的信息。
今天我设法解决了我的问题,所以我将解决方案放在这里,尽管我有点怀疑是否有很多人 运行 遇到同样的问题。
基本上,所需要的只是在强制门户服务器上的请求处理期间某处的绝对路径重定向。例如,在我的例子中,您同意我的 T&C 的索引页面上的表格正在调用操作 /agree
。这意味着客户端相信他正在访问他的原始目标服务器上的那些路径(例如 google.com/agree)。
使用绝对形式 10.0.0.1/agree
,客户端将在 iptables 调用后遵循正确的重定向。
抱歉,标题含糊不清,但我的问题解释起来有点复杂。
我在 cherrypy 中为 WLAN 接入点写了一个 "captive portal",它只是一个服务器,在地址在特定页面注册之前阻止 MAC 地址访问互联网。为此,我写了一些 iptables 规则,将所有 HTTP 流量重定向到我
sudo iptables -t mangle -N internet
sudo iptables -t mangle -A PREROUTING -i $DEV_IN -p tcp -m tcp --dport 80 -j internet
sudo iptables -t mangle -A internet -j MARK --set-mark 99
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -m mark --mark 99 -m tcp --dport 80 -j DNAT --to-destination 10.0.0.1
(此设置的细节对我的问题来说并不重要,只需注意创建了一个 "internet" 链,它将 HTTP 重定向到接入点上的端口 80)
在 AP 的 80 端口,cherrypy 服务器提供一个带有 "register" 按钮的静态登陆页面,该按钮向 http://10.0.0.1/agree 发出 POST 请求。为了处理这个请求,我创建了一个这样的方法:
@cherrypy.expose
def agree(self, **kwargs):
#retrieve MAC address of client by checking ARP table
ip = cherrypy.request.remote.ip
mac = str(os.popen("arp -a " + str(ip) + " | awk '{ print }' ").read())
mac = mac.rstrip('\r\n')
#add an iptables rule to whitelist the client, rmtrack to remove previous connection information
os.popen("sudo iptables -I internet 1 -t mangle -m mac --mac-source %s -j RETURN" %mac)
os.popen("sudo rmtrack %s" %ip)
return open('welcome.html')
因此此方法从 arp table 中检索客户端的 MAC 地址,然后添加一个 iptables 异常以从 "internet" 将流量重定向到门户的链。
现在,当我测试此设置时,发生了一些有趣的事情。在 iptables 中添加例外是有效的——即客户端现在可以访问网页而无需重定向到我。问题是 初始请求 没有到达我的服务器,即页面 welcome.html
从未打开 - 相反,在 iptables 之后并执行 rmtrack 调用时,客户端尝试在重定向到我的门户之前在他们请求的页面上打开 "agree" 路径。
例如,如果他们在地址栏中点击 "google.com",然后被发送到我的门户并同意,他们现在会尝试打开 http://google.com/agree。结果,他们在一段时间后得到一个错误。似乎 iptables 或 rmtrack 调用将请求更改为去往原始目的地 而 它仍在我的服务器上处理,这不会产生任何影响对我来说有意义。因此,在发出这些终端命令后,我 return 是哪个静态页面或进行了哪些重定向都无关紧要 - 客户端未使用我函数的 return 值。
我该如何解决这个问题?感谢每一条有用的信息。
今天我设法解决了我的问题,所以我将解决方案放在这里,尽管我有点怀疑是否有很多人 运行 遇到同样的问题。
基本上,所需要的只是在强制门户服务器上的请求处理期间某处的绝对路径重定向。例如,在我的例子中,您同意我的 T&C 的索引页面上的表格正在调用操作 /agree
。这意味着客户端相信他正在访问他的原始目标服务器上的那些路径(例如 google.com/agree)。
使用绝对形式 10.0.0.1/agree
,客户端将在 iptables 调用后遵循正确的重定向。