使用启用了防火墙的 websocketpp 接受连接的问题
Issue with accepting connection using websocketpp with firewall enabled
这个问题是我遇到过的最奇怪的 5 件事之一。所以请多多包涵。
我是 运行 arch linux(截至 2017-03-09 为止的最新版本),使用 ufw 防火墙。
启用防火墙后,我无法再连接到基于 websocketpp 的应用程序。不,我没有阻止相关端口。
事实上,如果我禁用防火墙,我仍然无法连接,直到我重新启动整个计算机(只是重新启动有问题的应用程序没有帮助)。
而且,UFW 也允许本地主机上的所有流量,但无论我是否在本地连接都没有区别。
我也在 websocketpp repository 中验证了示例回显服务器的问题。
检查我的应用程序是否在端口 9002 上侦听
sudo netstat -lnp | grep 900
tcp6 0 0 :::9002 :::* LISTEN 12695/./bin/echo_se
这里可以看到echo server绑定了ipv6。但是仅更改为 ipv4 无济于事。已经试过了。
带调试的回显服务器输出
[2017-03-09 11:38:06] [devel] endpoint constructor
[2017-03-09 11:38:06] [devel] server constructor
[2017-03-09 11:38:06] [devel] asio::init_asio
[2017-03-09 11:38:06] [devel] set_message_handler
[2017-03-09 11:38:06] [devel] asio::listen
[2017-03-09 11:38:06] [devel] create_connection
[2017-03-09 11:38:06] [devel] asio con transport constructor
[2017-03-09 11:38:06] [devel] connection constructor
[2017-03-09 11:38:06] [devel] transport::asio::init
[2017-03-09 11:38:06] [devel] asio::async_accept
我正在使用 telnet 尝试连接(因为此时我只关心 tcp 握手
telnet localhost 9002
Trying ::1...
(eventually timeout)
如果我关闭回声服务器,那么就没有应用程序在监听了。然后我得到(如预期的那样)
telnet localhost 9002
Trying ::1...
Connection failed: Connection refused
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
所以,现在 OS 注意到没有人在监听并且发送连接被拒绝。
UWF 规则:
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
22 ALLOW Anywhere
7000:8000/udp ALLOW Anywhere
7000:8000/tcp ALLOW Anywhere
9000:9500/tcp ALLOW Anywhere
9002 ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
22 (v6) ALLOW Anywhere (v6)
7000:8000/tcp (v6) ALLOW Anywhere (v6)
9000:9500/tcp (v6) ALLOW Anywhere (v6)
9002 (v6) ALLOW Anywhere (v6)
我还应该提到其他服务器。例如我在同一端口上尝试过的最小提升 asio telnet 服务器、基于 zmq 的服务器等工作正常。
所以,我认为它一定是 websocketpp 的东西,但我不明白它可能是什么。感觉不可能,因为 tcp 握手是在应用程序级别下执行的。
欢迎提出任何想法。
为了完整性。禁用 UFW 并重新启动后,我从 echo 服务器得到了这个:
2017-03-09 11:49:17] [devel] endpoint constructor
[2017-03-09 11:49:17] [devel] server constructor
[2017-03-09 11:49:17] [devel] asio::init_asio
[2017-03-09 11:49:17] [devel] set_message_handler
[2017-03-09 11:49:17] [devel] asio::listen
[2017-03-09 11:49:17] [devel] create_connection
[2017-03-09 11:49:17] [devel] asio con transport constructor
[2017-03-09 11:49:17] [devel] connection constructor
[2017-03-09 11:49:17] [devel] transport::asio::init
[2017-03-09 11:49:17] [devel] asio::async_accept
[2017-03-09 11:49:23] [devel] asio::handle_accept
[2017-03-09 11:49:23] [devel] connection start
[2017-03-09 11:49:23] [devel] asio connection init
[2017-03-09 11:49:23] [devel] asio connection handle pre_init
[2017-03-09 11:49:23] [devel] asio connection post_init
[2017-03-09 11:49:23] [devel] asio connection handle_post_init
[2017-03-09 11:49:23] [devel] connection handle_transport_init
[2017-03-09 11:49:23] [devel] connection read_handshake
[2017-03-09 11:49:23] [devel] asio async_read_at_least: 1
[2017-03-09 11:49:23] [devel] create_connection
[2017-03-09 11:49:23] [devel] asio con transport constructor
[2017-03-09 11:49:23] [devel] connection constructor
[2017-03-09 11:49:23] [devel] transport::asio::init
[2017-03-09 11:49:23] [devel] asio::async_accept
[2017-03-09 11:49:23] [devel] asio post init timer cancelled
在 telnet 中:
telnet localhost 9002
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
那么一切正常。
和"after sudo ufw enable && sudo ufw disable"
它不再起作用了...
好的,调试了两天(前一天写题然后今天)找到了。
OS 的 listen() 调用中的积压参数为 0。当加载 UFW/iptables 时,这会导致服务器无法正常运行,否则服务器会正常运行。
为什么加载或不加载 iptables 时行为不同对我来说是个谜。
This post 建议即使设置为 0,积压也应该至少为 16。也许(这是我的猜测)加载 iptables 后内核不再汇总积压参数和 0 原因它到 "not work"。我能理解,因为队列为 0 没有意义。
总之。将 backlog 设置为 64 解决了我的问题。
websocketPpServerObject.set_listen_backlog(64);
如果您对更多详细信息感兴趣,另请参阅 this github thread。
这个问题是我遇到过的最奇怪的 5 件事之一。所以请多多包涵。
我是 运行 arch linux(截至 2017-03-09 为止的最新版本),使用 ufw 防火墙。
启用防火墙后,我无法再连接到基于 websocketpp 的应用程序。不,我没有阻止相关端口。
事实上,如果我禁用防火墙,我仍然无法连接,直到我重新启动整个计算机(只是重新启动有问题的应用程序没有帮助)。
而且,UFW 也允许本地主机上的所有流量,但无论我是否在本地连接都没有区别。
我也在 websocketpp repository 中验证了示例回显服务器的问题。
检查我的应用程序是否在端口 9002 上侦听
sudo netstat -lnp | grep 900
tcp6 0 0 :::9002 :::* LISTEN 12695/./bin/echo_se
这里可以看到echo server绑定了ipv6。但是仅更改为 ipv4 无济于事。已经试过了。
带调试的回显服务器输出
[2017-03-09 11:38:06] [devel] endpoint constructor
[2017-03-09 11:38:06] [devel] server constructor
[2017-03-09 11:38:06] [devel] asio::init_asio
[2017-03-09 11:38:06] [devel] set_message_handler
[2017-03-09 11:38:06] [devel] asio::listen
[2017-03-09 11:38:06] [devel] create_connection
[2017-03-09 11:38:06] [devel] asio con transport constructor
[2017-03-09 11:38:06] [devel] connection constructor
[2017-03-09 11:38:06] [devel] transport::asio::init
[2017-03-09 11:38:06] [devel] asio::async_accept
我正在使用 telnet 尝试连接(因为此时我只关心 tcp 握手
telnet localhost 9002
Trying ::1...
(eventually timeout)
如果我关闭回声服务器,那么就没有应用程序在监听了。然后我得到(如预期的那样)
telnet localhost 9002
Trying ::1...
Connection failed: Connection refused
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
所以,现在 OS 注意到没有人在监听并且发送连接被拒绝。
UWF 规则:
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
22 ALLOW Anywhere
7000:8000/udp ALLOW Anywhere
7000:8000/tcp ALLOW Anywhere
9000:9500/tcp ALLOW Anywhere
9002 ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
22 (v6) ALLOW Anywhere (v6)
7000:8000/tcp (v6) ALLOW Anywhere (v6)
9000:9500/tcp (v6) ALLOW Anywhere (v6)
9002 (v6) ALLOW Anywhere (v6)
我还应该提到其他服务器。例如我在同一端口上尝试过的最小提升 asio telnet 服务器、基于 zmq 的服务器等工作正常。
所以,我认为它一定是 websocketpp 的东西,但我不明白它可能是什么。感觉不可能,因为 tcp 握手是在应用程序级别下执行的。
欢迎提出任何想法。
为了完整性。禁用 UFW 并重新启动后,我从 echo 服务器得到了这个:
2017-03-09 11:49:17] [devel] endpoint constructor
[2017-03-09 11:49:17] [devel] server constructor
[2017-03-09 11:49:17] [devel] asio::init_asio
[2017-03-09 11:49:17] [devel] set_message_handler
[2017-03-09 11:49:17] [devel] asio::listen
[2017-03-09 11:49:17] [devel] create_connection
[2017-03-09 11:49:17] [devel] asio con transport constructor
[2017-03-09 11:49:17] [devel] connection constructor
[2017-03-09 11:49:17] [devel] transport::asio::init
[2017-03-09 11:49:17] [devel] asio::async_accept
[2017-03-09 11:49:23] [devel] asio::handle_accept
[2017-03-09 11:49:23] [devel] connection start
[2017-03-09 11:49:23] [devel] asio connection init
[2017-03-09 11:49:23] [devel] asio connection handle pre_init
[2017-03-09 11:49:23] [devel] asio connection post_init
[2017-03-09 11:49:23] [devel] asio connection handle_post_init
[2017-03-09 11:49:23] [devel] connection handle_transport_init
[2017-03-09 11:49:23] [devel] connection read_handshake
[2017-03-09 11:49:23] [devel] asio async_read_at_least: 1
[2017-03-09 11:49:23] [devel] create_connection
[2017-03-09 11:49:23] [devel] asio con transport constructor
[2017-03-09 11:49:23] [devel] connection constructor
[2017-03-09 11:49:23] [devel] transport::asio::init
[2017-03-09 11:49:23] [devel] asio::async_accept
[2017-03-09 11:49:23] [devel] asio post init timer cancelled
在 telnet 中:
telnet localhost 9002
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
那么一切正常。
和"after sudo ufw enable && sudo ufw disable" 它不再起作用了...
好的,调试了两天(前一天写题然后今天)找到了。
OS 的 listen() 调用中的积压参数为 0。当加载 UFW/iptables 时,这会导致服务器无法正常运行,否则服务器会正常运行。
为什么加载或不加载 iptables 时行为不同对我来说是个谜。
This post 建议即使设置为 0,积压也应该至少为 16。也许(这是我的猜测)加载 iptables 后内核不再汇总积压参数和 0 原因它到 "not work"。我能理解,因为队列为 0 没有意义。
总之。将 backlog 设置为 64 解决了我的问题。
websocketPpServerObject.set_listen_backlog(64);
如果您对更多详细信息感兴趣,另请参阅 this github thread。