业务需求
当业务上需要使用ping命令对主机进行心跳探测时,首先想到的是利用代码fork进程执行ping命令,如果自己实现,代码量大,处理流容易出错,和使用标准库比起来相当不优雅.于是查阅了一下资料
按资料上的说法,java的InetAddress的isReachable方法在root用户下使用ping命令探测,非root用户下使用端口7探测
书写了demo代码进行了测试,demo地址https://github.com/Shoothzj/heart-beat
package com.github.shoothzj.heartbeat.ping.test;
import lombok.extern.slf4j.Slf4j;
import java.net.InetAddress;
/**
* @author hezhangjian
*/
@Slf4j
public class PingTestMain {
public static void main(String[] args) throws Exception {
String testIp = System.getProperty("TestIp");
InetAddress inetAddress = InetAddress.getByName(testIp);
boolean addressReachable = inetAddress.isReachable(500);
log.info("address is reachable is {}", addressReachable);
}
}
测试场景
root用户下执行程序
java程序打印结果也是true
切换到普通用户执行程序
此时可以看到,我们的客户端程序向目标tcp7端口发送了一个报文,虽然java程序打印结果为true,但是因为收到了RST包导致的.在当今的网络安全要求下,7端口往往不会开放
屏蔽目标网络的7端口执行程序
iptables -A INPUT -p tcp --dport 7 -j DROP
发送的报文没有收到RST包,此时java程序返回false.不是我们预期的结果
普通用户携带特权
通过查阅资料,发现java发送ping命令,需要创建raw socket
只有root权限或者拥有cap_net_raw权限才可以创建raw socket,所以我们赋予java程序创建raw socket的权限再次尝试
setcap cap_net_raw+ep /usr/java/jdk-13.0.1/bin/java
发现如下报错
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
使用https://askubuntu.com/questions/334365/how-to-add-a-directory-to-linker-command-line-in-linux规避添加so文件权限
随后抓包,发现还是发送了ping命令,达到了我们预期的效果
总结
root用户会使用ping命令探测. 如果普通用户不携带特权会探测tcp7端口,如果7端口安全组不开启会与预期结果不一致,推荐赋予java程序特权,就会使用ping命令探测