簡體   English   中英

在 Windows 平台上使用 Java 查找特定路由的傳出 IP 地址

[英]Finding outgoing IP address for specific route using Java on Windows platform

盡管有很多線程使用NetworkInterfaceInterfaceAddressInetAddress組合來查找機器 IP 地址,但我的情況遠不止於此。

我需要確定在與特定(給定)目標通信期間將使用的傳出 IP 地址。 我必須假設主機上可能有多個具有許多 ip 地址的接口。 這是我可以想象的最佳近似值,用於現實生活場景,我必須向僅通過 IP 地址知道的遠程機器提供一個自己的 IP,它可以用來訪問我的主機。

到目前為止,我還沒有找到針對此任務的純 Java 解決方案。 以我非常有限的 Java 知識,我看不出分析可能的路由選項的簡單方法。 這就是為什么在 Linux 上我只會在外部執行並解析類似的東西:

ip -o route get 10.10.xx.xx

這反過來會給我想要的值(“src xx.xx.xx.xx”):

10.10.xx.xx dev eth1  src 10.20.xx.xx \    cache  mtu 1500 advmss 1460 hoplimit 64

我的問題是是否有一種本地方式可以在不調用上述外部命令的情況下實現相同的結果。 如果不是,那么您對 ​​Windows 等效建議是什么?


我還嘗試使用InetAddress.isReachable(...)和具有給定源地址的外部ping ,但前者在回退到 TCP 回顯時在我的環境中的防火牆上失敗,而另一個則提供誤報。 (在我的測試 VM 上,我有一個接口直接綁定到主機網絡,第二個接口作為通過 VM 主機的網橋 (NAT)。因此,對於 ping 兩條路由,不支持在相反方向上按要求通過主機路由。)

我將不勝感激任何建議如何繼續...

最后我最終解析了路由表(僅限 IP4,沒有靜態路由)。 這是一個代碼片段,也許它對某人有用。 更具體的路線比更通用的路線更受歡迎。 對於相同的網絡部分長度,最佳指標獲勝。

private static String findOutgoingIpForGivenAdress(String remoteIP) {
    final String COMMAND = "route print -4";
    List<RouteInfo> routes = new ArrayList<>();
    try {
        Process exec = Runtime.getRuntime().exec(COMMAND);
        BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream()));

        String localIP = null;
        String line;
        /* examples:
                0.0.0.0          0.0.0.0     10.172.180.1    10.172.180.36     20
                0.0.0.0          0.0.0.0      10.187.20.1    10.187.20.225     25
           10.172.180.0    255.255.255.0         On-link     10.172.180.36    276
          10.172.180.36  255.255.255.255         On-link     10.172.180.36    276
        */
        Pattern p = Pattern.compile("^\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+\\S+?\\s+(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+(\\d+)\\s*$");
        while ((line = reader.readLine()) != null) {
            Matcher match = p.matcher(line);
            if (match.matches()) {
                String network = match.group(1);
                String mask = match.group(2);
                String address = match.group(3);
                short maskLength = 0;
                boolean networkMatch = network.contentEquals("0.0.0.0");
                if (!networkMatch) {
                    SubnetUtils subnet = new SubnetUtils(network, mask);
                    SubnetUtils.SubnetInfo info = subnet.getInfo();
                    networkMatch = info.isInRange(remoteIP);
                    maskLength = Short.valueOf(info.getCidrSignature().split("/")[1]);
                }
                if (networkMatch) {
                    short metric = Short.valueOf(match.group(4));
                    routes.add(new RouteInfo(address, maskLength, metric));
                }
            }
        }
        Collections.sort(routes);
        for (RouteInfo route : routes) {
        }
        if (!routes.isEmpty())
            return routes.get(0).source;
        if (localIP != null)
            return localIP;
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

還有RouteInfo幫助類:

public class RouteInfo implements Comparable<RouteInfo> {
    public final String source;
    public final short maskLength;
    public final short metric;

    public RouteInfo(String src, short mask, short mtr) {
        source = src;
        maskLength = mask;
        metric = mtr;
    }

    @Override
    public int compareTo(RouteInfo ri) {
        if (ri.maskLength != maskLength)
            return ri.maskLength - maskLength;
        return metric - ri.metric;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM