Skip to content

[JENKINS-48561] JNLP agent doesn't take into account -Dhttp.nonProxyHosts #1291

Description

@jenkins-infra-bot

This is a followup of JENKINS-32326 and JENKINS-32326 which aimed to implement full support of proxy and exclusions list in remoting lib.

 

Our network is behind a corporate proxy which requires us to properly configure our tools to access Internet.

For most of our CLI tools, we rely on the no_proxy environment variables to set the list of exclusions. Unfortunately, this variable (and the associated logic) does not support wildcard and can only contain a limited number of chars. That means that we can only whitelist some IP addresses and FQDN.

For Java-based tool, we use the system property http.nonProxyHosts which is much more convenient since it supports wildcard and regex.

Our Jenkins agents are executed in environment which contain the aforementioned environment variables, in a JVM with the corresponding system properties as well.

Some part of the remoting lib seems to give precedence to environment variables over system properties. Meaning that if the master IP address is in the system property but not in the env var, the agent will try to go through the proxy and timeout.

Test case

  • Command: java -cp /path/to/remoting.jar hudson.remoting.jnlp.Main -headless -url http://172.17.0.1:8080
  • System properties:
    • -Dhttp.proxyHost=200.xxx.xxx.xxx
    • -Dhttp.proxyPort=80
    • -Dhttp.nonProxyHosts=172.17.0.1
  • Environment variables:

Expected behavior

Agent connects to the master since its IP address is in the exclusion list defined by a system property which has precedence over the corresponding environment variable.

Issue

Agent successfully validates the provided credentials and checks that the master is up and running, but timeout when trying to open the JNLP channel.

Analysis

ProxySelector.getDefault() resolves to sun.net.spi.DefaultProxySelector which is a basic helper to retrieve all available proxy connections defined with system properties and/or provided by the operating system.

DefaultProxySelector.select() will return a list of Proxy object which are relevant to the provided URL in argument (e.g. http://172.17.0.1).

The most important information of the Proxy object is its type which can either be:

  • Type.DIRECT: direct connection to the URL without going through a proxy
  • Type.HTTP: connection through a HTTP proxy
  • Type.SOCKS: connection through a SOCK proxy

By default, a Proxy has a DIRECT type. The static variable Proxy.NO_PROXY is an alias to the default constructor.

In JnlpAgentEndpointResolver, when the returned proxy is of type DIRECT, the while loop is terminated: JnlpAgentEndpointResolver#338. When exiting the loop, no value has been assigned to targetAddress which is still equal to null.

At JnlpAgentEndpointResolver#354, the script fallbacks to the proxy environment variables if targetAddress is still null.

Unfortunately in our case, DefaultProxySelector.select() will return a unique proxy of type DIRECT because the system property http.nonProxyHosts does contain the URL in argument (172.17.0.1).

Even if you don't go through the entire logic of DefaultProxySelector.select(), it is fairly easy to draw general conclusion from this test: ProxySelector.getDefault().select(URI.create("http://172.17.0.1:80")) will return:

  • Proxy.NO_PROXY when the system property is not set
  • Proxy.NO_PROXY when the system property is http.nonProxyHosts=172.17.0.1
  • "HTTP @ 200.xxx.xxx.xxx:80" when the system property is http.nonProxyHosts=127.0.0.1

Originally reported by etiennebec, imported from: JNLP agent doesn't take into account -Dhttp.nonProxyHosts
  • assignee: etiennebec
  • status: Resolved
  • priority: Major
  • component(s): remoting
  • resolution: Fixed
  • resolved: 2018-03-13T21:48:38+00:00
  • votes: 0
  • watchers: 2
  • imported: 2025-11-25
Raw content of original issue

This is a followup of JENKINS-32326 and JENKINS-32326 which aimed to implement full support of proxy and exclusions list in remoting lib.

 

Our network is behind a corporate proxy which requires us to properly configure our tools to access Internet.

For most of our CLI tools, we rely on the no_proxy environment variables to set the list of exclusions. Unfortunately, this variable (and the associated logic) does not support wildcard and can only contain a limited number of chars. That means that we can only whitelist some IP addresses and FQDN.

For Java-based tool, we use the system property http.nonProxyHosts which is much more convenient since it supports wildcard and regex.

Our Jenkins agents are executed in environment which contain the aforementioned environment variables, in a JVM with the corresponding system properties as well.

Some part of the remoting lib seems to give precedence to environment variables over system properties. Meaning that if the master IP address is in the system property but not in the env var, the agent will try to go through the proxy and timeout.

Test case

  • Command: java -cp /path/to/remoting.jar hudson.remoting.jnlp.Main -headless -url http://172.17.0.1:8080 <agent_secret> <agent_name>
  • System properties:
    • -Dhttp.proxyHost=200.xxx.xxx.xxx
    • -Dhttp.proxyPort=80
    • -Dhttp.nonProxyHosts=172.17.0.1
  • Environment variables:

Expected behavior

Agent connects to the master since its IP address is in the exclusion list defined by a system property which has precedence over the corresponding environment variable.

Issue

Agent successfully validates the provided credentials and checks that the master is up and running, but timeout when trying to open the JNLP channel.

Analysis

ProxySelector.getDefault() resolves to sun.net.spi.DefaultProxySelector which is a basic helper to retrieve all available proxy connections defined with system properties and/or provided by the operating system.

DefaultProxySelector.select() will return a list of Proxy object which are relevant to the provided URL in argument (e.g. http://172.17.0.1).

The most important information of the Proxy object is its type which can either be:

  • Type.DIRECT: direct connection to the URL without going through a proxy
  • Type.HTTP: connection through a HTTP proxy
  • Type.SOCKS: connection through a SOCK proxy

By default, a Proxy has a DIRECT type. The static variable Proxy.NO_PROXY is an alias to the default constructor.

In JnlpAgentEndpointResolver, when the returned proxy is of type DIRECT, the while loop is terminated: JnlpAgentEndpointResolver#338. When exiting the loop, no value has been assigned to targetAddress which is still equal to null.

At JnlpAgentEndpointResolver#354, the script fallbacks to the proxy environment variables if targetAddress is still null.

Unfortunately in our case, DefaultProxySelector.select() will return a unique proxy of type DIRECT because the system property http.nonProxyHosts does contain the URL in argument (172.17.0.1).

Even if you don't go through the entire logic of DefaultProxySelector.select(), it is fairly easy to draw general conclusion from this test: ProxySelector.getDefault().select(URI.create("http://172.17.0.1:80")) will return:

  • Proxy.NO_PROXY when the system property is not set
  • Proxy.NO_PROXY when the system property is http.nonProxyHosts=172.17.0.1
  • "HTTP @ 200.xxx.xxx.xxx:80" when the system property is http.nonProxyHosts=127.0.0.1
  • environment: Jenkins 2.73.3 with remoting 3.10.2 on OracleJDK 1.8

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions