Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP Proxy is not supported #170

Closed
missedone opened this issue Jan 22, 2015 · 13 comments
Closed

HTTP Proxy is not supported #170

missedone opened this issue Jan 22, 2015 · 13 comments
Assignees
Labels

Comments

@missedone
Copy link

Hi Folks

as we work behind the firewall, the SSH connection need go over HTTP proxy, but I found SSHj only support SOCKS proxy. here is the code snappet with HTTP proxy

try (SSHClient ssh = new SSHClient()) {
            ssh.setConnectTimeout(60 * 1000);
            ssh.setTimeout(60 * 60 * 1000);
            ssh.getConnection().getKeepAlive().setKeepAliveInterval(30);
            ssh.loadKnownHosts();
            ssh.addHostKeyVerifier(new PromiscuousVerifier());

            ssh.connect(host, new Proxy(Proxy.Type.HTTP, new InetSocketAddress("16.85.88.10", 8080)));
            ssh.authPublickey(user, ssh.loadKeys(privateKey, null, null));

            try (Session session = ssh.startSession()) {
                final Session.Command cmd = session.exec("echo sleeping && date && sleep 3000 && date && echo awake");
                System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
                cmd.join(90, TimeUnit.MINUTES);
                System.out.println("\n** exit status: " + cmd.getExitStatus());
            }
        }

i got exception:

java.lang.IllegalArgumentException: Invalid Proxy
    at java.net.Socket.<init>(Socket.java:147)
    at net.schmizz.sshj.SocketClient.connect(SocketClient.java:57)
    at net.schmizz.sshj.SocketClient.connect(SocketClient.java:71)
    at net.schmizz.sshj.SocketClient.connect(SocketClient.java:107)
    at com.hp.es.cto.sp.remote.SshjTest.testKeepAlive(SshjTest.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

by dig into the source code of java.net.Socket.Socket(Proxy), we can see it only support SOCKS and NO_PROXY proxy.

I saw both jsch and ganymed support HTTP proxy, so would you consider to add HTTP proxy support? thanks

@ghost
Copy link

ghost commented Jan 22, 2015

You could use custom socket factory

@hierynomus
Copy link
Owner

I don't get it, if I look at my JDK's source code, I see the following in the constructor:

    public Socket(Proxy proxy) {
        // Create a copy of Proxy as a security measure
        if (proxy == null) {
            throw new IllegalArgumentException("Invalid Proxy");
        }
        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY
                                          : sun.net.ApplicationProxy.create(proxy);
        Proxy.Type type = p.type();
        if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) {

So it actually supports HTTP Proxies. Which JDK are you using?

@missedone
Copy link
Author

right, i'm using Oracle JDK 1.7.x which is the version we used on our production
when I switch to JDK 1.8, it does works.
do you have any idea to make it back ported though i will check it via google search as well.
thanks

@hierynomus
Copy link
Owner

I might have found something... will try to implement this next week. In
the meantime though I'm going to release 0.11.0 without this.

Regards,
Jeroen

2015-01-23 5:35 GMT+01:00 Nick Tan notifications@github.com:

right, i'm using Oracle JDK 1.7.x which is the version we used on our
production
when I switch to JDK 1.8, it does works.
do you have any idea to make it back ported though i will check it via
google search as well.
thanks


Reply to this email directly or view it on GitHub
#170 (comment).

@missedone
Copy link
Author

Thanks Jeroen

@hierynomus hierynomus added this to the v0.12.0 milestone Jan 23, 2015
@hierynomus hierynomus self-assigned this Jan 23, 2015
@dkocher
Copy link
Contributor

dkocher commented Mar 30, 2015

I don't understand why this needs its own implementation and doesn't rely on using the JDK internal HTTP tunneling support using the Socket(Proxy.Type.HTTP)constructor which then delegates to the java.net.HttpConnectSocketImpl implementation. I tend to say providing an proxy implementation should be out of scope for sshj. The change in fc535a5 breaks API compatibility for users that want to provide a custom socket factory implementation.

@hierynomus
Copy link
Owner

Hi David, I also thought that would work, unfortunately for JDK6 and 7, sockets with HTTP proxies are not implemented. See the code here:

    public Socket(Proxy proxy) {
        // Create a copy of Proxy as a security measure
        if (proxy == null) {
            throw new IllegalArgumentException("Invalid Proxy");
        }
        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy);
        if (p.type() == Proxy.Type.SOCKS) {
            SecurityManager security = System.getSecurityManager();
            InetSocketAddress epoint = (InetSocketAddress) p.address();
            if (epoint.getAddress() != null) {
                checkAddress (epoint.getAddress(), "Socket");
            }
            if (security != null) {
                if (epoint.isUnresolved())
                    epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort());
                if (epoint.isUnresolved())
                    security.checkConnect(epoint.getHostName(), epoint.getPort());
                else
                    security.checkConnect(epoint.getAddress().getHostAddress(),
                                  epoint.getPort());
            }
            impl = new SocksSocketImpl(p);
            impl.setSocket(this);
        } else {
            if (p == Proxy.NO_PROXY) {
                if (factory == null) {
                    impl = new PlainSocketImpl();
                    impl.setSocket(this);
                } else
                    setImpl();
            } else
                throw new IllegalArgumentException("Invalid Proxy");
        }

@hierynomus hierynomus reopened this Mar 30, 2015
@hierynomus
Copy link
Owner

I've reopened the issue to actually correct the SocketFactory to correctly implement the SocketFactory interface so as not to break the external API as David mentions.

@dkocher
Copy link
Contributor

dkocher commented Mar 30, 2015

Yes, support was introduced with HttpConnectSocketImpl in 1.8. I still think it is acceptable for users that require this to run Java 1.8 or later that need this and default to the provided implementation in the JDK. Or they can write their own socket factory implementation and provide HTTP Connect proxy support.

@hierynomus
Copy link
Owner

Ok, changed the implementation for this, no custom SocketFactory anymore. The entire proxy support actually already bypassed the proxy factory. That should have been implemented differently from the start. I'll mark those methods deprecated and suggest that you should use a custom SocketFactory for that. For now, it will work with different versions of Java.

@hierynomus
Copy link
Owner

@dkocher Let me know whether you like this one better ;)

@dkocher
Copy link
Contributor

dkocher commented Mar 30, 2015

Thanks for taking my input into account. +1 for marking the constructors with proxy parameter as deprecated.

@hierynomus
Copy link
Owner

Thanks for contributing and noticing I broke the API 😉. Deprecations are marked in 4250c61

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants