操作系统版本:Centos 7 2003
开发人员反馈通过socat做正向代理,连接socat代理返回permission denied,根据日志查看发现执行connect函数时返回EACCES,即permission denied。注:程序是root用户执行的
man connect查看返回错误可能原因:
EACCES For Unix domain sockets, which are identified by pathname: Write permission is denied on the socket file, or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)
EACCES, EPERM
The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the connection request failed because of a local firewall rule.
以为是操作系统防火墙或selinux问题,通过排查发现防火墙是关闭的,selinux也未启用
换nc测试,发现nc与socat返回结果相同,也是没有权限
跟踪调用栈
通过perf record -p PID -ag,再根据perf script得到socat程序执行connect时内核中的调用栈:
根据内核源码发现,从调用栈中的filter_get_sock_type函数开始就不属于内核源码,因此想到一种可能,就是安装了其他的内核模块。
进一步查看内核模块:执行lsmod,发现系统中很多内核模块,根据内核模块名通过find / -name '内核模块名*'查找内核模块路径,找到后执行nm '内核模块名绝对路径' | grep filter_get_sock_type,在其中某个模块中果然找到此函数,剩下的函数同样方法查找,也都在此模块中,因此问题发现,原因是客户安装了自己或第三方实现的防火墙,此防火墙阻止了相关程序执行connect函数