Java + Kerberos - 禁用反向DNS查找

时间:2018-01-10 17:46:18

标签: java kerberos

我们正在使用Apache HttpClient库来连接到Kerberos安全的REST端点,该端点位于为多个应用程序提供服务的负载均衡器后面,因此正向和反向DNS查找结果之间存在不匹配。

虽然我们可以通过在krb5.conf文件中设置rdns = false来使用cURL成功建立经过身份验证的会话,但在Java中似乎不可能 - 它只是忽略此设置并始终执行反向DNS查找,由于不匹配,当然会失败。

我没有找到关于这个问题的太多信息,但我确实找到了这个开放的Jira项目,它解释了我们看到的行为......但没有提供任何解决方法: https://bugs.openjdk.java.net/browse/JDK-8189361

到目前为止,我发现的唯一可行的解​​决方法是使用自定义名称服务提供程序“劫持”反向DNS查找并返回所需的主机名。
关于这方面也有非常稀少的信息,但我发现这个近12年前的博客文章似乎仍然有用(虽然感觉就像一个非常脏的黑客):
http://rkuzmik.blogspot.co.il/2006/08/local-managed-dns-java_11.html

然而,感觉我可能在这里遗漏了一些东西,因为似乎不太可能有关于这个问题的信息很少。

在Java中执行Kerberos时,还有其他人遇到过禁用反向DNS查找的问题吗?如果是这样,你是如何解决的。

3 个答案:

答案 0 :(得分:3)

上周我使用VIP时遇到了同样的错误,但反向dns给了我物理服务器的FQDN。 不幸的是,我没有直接使用HttpClient-4.5.1库,而是在幕后使用它的软件;出于这个原因,我一直在寻找一个解决方案而不涉及该软件的源代码。 我确实做了大量的试验(jvm spi.dns,jvm gss native,dnsjava.jar,...),但遗憾的是没有任何成功。 最后,"脏解决方案"我一直在重建HttpClient jar来改变类" org.apache.http.impl.auth.GGSSchemeBase" on the method" String resolveCanonicalHostname(final String host)"。

对于一个可能的"好的解决方案",我看到这个类正在接收参数" boolean useCanonicalHostname"直接在它的构造函数中,如果您可以直接使用HttpClient库,可能有一种方法将此参数设置为false并将其传播到生成kerberos服务票证的此类(如果参数为false,则rdns检查未完成,而是使用主机字符串)。

我希望这个提示可以帮助你。

BR

Samuele

答案 1 :(得分:1)

对于使用Apache HttpClient库遇到同样问题的任何人,下面的代码都可以使用 - 重要的是SPNegoSchemeFactory的构造函数,它是:

public SPNegoSchemeFactory(final boolean stripPort, final boolean useCanonicalHostname)

以下是我现在使用的Scala代码:

  private val registry = RegistryBuilder
    .create()
    .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true,false))
    .build()
    .asInstanceOf[Lookup[AuthSchemeProvider]]

  private val credentialsProvider = new BasicCredentialsProvider

  private val useJaasCreds = new Credentials()
  {
    def getPassword: String = null

    def getUserPrincipal: Principal = null
  }

  credentialsProvider.setCredentials(new AuthScope(null, -1, null), useJaasCreds)

  private val httpClient = HttpClientBuilder
    .create()
    .setDefaultAuthSchemeRegistry(registry)
      .setDefaultCredentialsProvider(credentialsProvider)
    .build()

答案 2 :(得分:1)

我遇到了同样的问题,经过调查后发现,现有的 Java HTTP / Kerberos 客户端都无法完全控制生成 SPN 。所以我开始研究一个独立的库,它允许生成和验证WWW-Authenticate: Negotiate XXX / URL url = new URL("http://cname.provider.acme.com/api/operation1"); SpnegoContext context = spnegoClient.createContext("http://cname.provider.acme.com"); // Will result in HTTP/cname.provider.acme.com SPN HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("Authorization", context.createTokenAsAuthroizationHeader()); HTTP 标题。

它被称为Kerb4J

考虑您有一个域 cname.provider.acme.com ,它是域 a.provider.acme.com 的CNAME(AKA别名),其规范 DNS 名称(即在反向DNS查找后解析)是 ptr.provider.acme.com

您想使用您最喜欢的 HTTP 客户端向 cname.provider.acme.com 发出请求,但不希望它对进行任何其他操作 SPN 计算期间的DNS

URL url = new URL("http://localhost:8080/api/operation1");
SpnegoContext context = spnegoClient.createContext("http://cname.provider.acme.com"); // Will result in HTTP/cname.provider.acme.com SPN
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", context.createTokenAsAuthroizationHeader());

使用 Kerb4J ,您甚至可以使用任意 SPN 来制作 SPNEGO 保护的请求(在本地计算机上测试代码时很有用):< / p>

predict_on_batch(self, x)

Returns predictions for a single batch of samples.

Arguments

    x: Input samples, as a Numpy array.

Returns

Numpy array(s) of predictions.

Maven Central中有一个已发布的版本。

免责声明:我是Kerb4J的作者。