Code Monkey home page Code Monkey logo

proxytunnel's Introduction

Build Status Maintainers Wanted

Proxytunnel

Author: Jos Visser [email protected], Mark Janssen [email protected]

Hi all,

This is proxytunnel, a program that connects stdin and stdout to an origin server somewhere in the Internet through an industry standard HTTPS proxy. I originally wrote this program to be used as an extension to SSH, to be able to SSH to my box at home. In this file, I will describe the use with SSH. If you want to use it with some other application, feel free, and let me know!

Build docs is here

Usage (man page is here):

Proxytunnel is very easy to use, when running proxytunnel with the help option it specifies it's command-line options.

$ ./proxytunnel --help
proxytunnel 1.12.1 Copyright 2001-2024 Proxytunnel Project
Usage: proxytunnel [OPTIONS]...
Build generic tunnels through HTTPS proxies using HTTP authentication

Standard options:
 -i, --inetd                Run from inetd (default: off)
 -a, --standalone=STRING    Run as standalone daemon on specified port or
                            address:port combination
 -p, --proxy=STRING         Local proxy host:port combination
 -r, --remproxy=STRING      Remote proxy host:port combination (using 2 proxies)
 -d, --dest=STRING          Destination host:port combination
 -e, --encrypt              SSL encrypt data between local proxy and destination
 -E, --encrypt-proxy        SSL encrypt data between client and local proxy
 -X, --encrypt-remproxy     SSL encrypt data between local and remote proxy

Additional options for specific features:
 -W, --wa-bug-29744         Workaround ASF Bugzilla 29744: if SSL is active
                            stop using it after CONNECT (might not work on all
                            setups)
 -B, --buggy-encrypt-proxy  Equivalent to -E -W, provided for backwards
                            compatibility
 -z, --no-check-certificate Don't verify server SSL certificate
 -C, --cacert=STRING        Path to trusted CA certificate or directory
 -4, --ipv4                 Enforce IPv4 connection to local proxy
 -6, --ipv6                 Enforce IPv6 connection to local proxy
 -F, --passfile=STRING      File with credentials for proxy authentication
 -P, --proxyauth=STRING     Proxy auth credentials user:pass combination
 -R, --remproxyauth=STRING  Remote proxy auth credentials user:pass combination
 -c, --cert=FILENAME        client SSL certificate (chain)
 -k, --key=FILENAME         client SSL key
 -N, --ntlm                 Use NTLM based authentication
 -t, --domain=STRING        NTLM domain (default: autodetect)
 -H, --header=STRING        Add additional HTTP headers to send to proxy
 -o, --host=STRING          Send custom Host Header/SNI
 -x, --proctitle=STRING     Use a different process title

Miscellaneous options:
 -v, --verbose              Turn on verbosity
 -q, --quiet                Suppress messages
 -h, --help                 Print help and exit
 -V, --version              Print version and exit

To use this program with OpenSSH to connect to a host somewhere, create a $HOME/.ssh/config file with the following content:

Host foobar
	ProtocolKeepAlives 30
	ProxyCommand /path/to/proxytunnel -E -p proxy:8080 -P username -d mybox.athome.nl:443

With:

- foobar		The symbolic name of the host you want to connect to
- -E			Option to use encryption to communicate to the proxy (use https)
- proxy			The host name of the proxy you want to connect through
- 8080			The port number where the proxy software listens to
- username		Your proxy userid (password will be prompted)
- mybox.athome.nl	The hostname of the box you want to connect to (ultimately)
- 443			The port number of the SSH daemon on mybox.athome.nl

Optional arguments:

- -z			Don't verify server SSL certificate (for example in case of self-signed certificate)

If your proxy doesn't require the username and password for using it, you can skip these options. If you don't provide the password on the command-line (which is recommended) you will be prompted for it by proxytunnel. If you are on a trusted system you can also put the password in the environment variable PROXYPASS.

If you want to run proxytunnel from inetd add the '--inetd' option.

Most HTTPS proxies do not allow access to ports other than 443 (HTTPS) and 563 (SNEWS), so some hacking is necessary to start the SSH daemon on the required port. (On the server side add an extra Port statement in the sshd_config file, or use a redirect rule in your firewall.)

When your proxy uses NTLM authentication (like Microsoft IIS proxy) you need to specify -N to enable NTLM, and then specify your username and password (and optionally domain, if autodetection fails). The NT domain can be specified on the commandline if the auto-detection doesn't work for you (which is usually doesn't)

If you want to have the first proxy connect to another http proxy (like one you can control, specify -r proxy2:port. The first proxy will then connect to this remote proxy, which will be asked to connect to the requested destination. For more information regarding this feature, check out http://dag.wieers.com/howto/ssh-http-tunneling/

If your proxy is more advanced, and does protocol inspection it will detect that your connection is not a real HTTPS/SSL connection. You can enable SSL encryption (using -e), which will work around this problem, however, you need to setup stunnel4 on the other side, or connect to a process that understands SSL itself.

When all this is in place, execute an "ssh foobar" and you're in business!

Environment Variables

Proxytunnel can make use of the following environment variables:

PROXYUSER		Username for the proxy-authentication
PROXYPASS		Password for the proxy-authentication
REMPROXYUSER		Username for remote proxy-authentication
REMPROXYPASS		Password for remote proxy-authentication
HTTP_PROXY		Primary proxy host and port information
			Format: HTTP_PROXY=http://<host>:<port>/

Authentication File

Proxytunnel can read authentication data from a file (-F/--passfile)

The format for this file is:

<field> = <value>
<field> = <value>
etc

One entry per line, 1 space before and after the equal sign.

The accepted fields are:

  • proxy_user
  • proxy_passwd
  • remproxy_user
  • remproxy_passwd

Share and Enjoy!

Jos Visser [email protected] Mark Janssen [email protected]

proxytunnel's People

Contributors

68420948 avatar adamgolebiowski avatar boerwastaken avatar dagwieers avatar defractal avatar gpchelkin avatar hoilc avatar ilovezfs avatar mcarbonneaux avatar niven avatar pghmcfc avatar sigio avatar stoecker avatar thehawke avatar yurivict avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proxytunnel's Issues

"Broken pipe" error when pressing Ctrl+C too fast or when Ctrl+C with slow connection

First of all big thanks to this project. Incredibly easy to use and saved me from having to setup a whole VPN just to SSH into my machine.

I have an SSH connection to a machine with a fair bit of latency due to being on the other side of the planet. Various situation cause client_loop: send disconnect: Broken pipe to be emitted and being thrown out of the SSH session.

The first once is pressing Ctrl+C twice in quick succession. When the prompt has not returned after Ctrl+C was emitted, then the above error occurs. Even when it's almost instant, with no process running.
Another such occasion is a hanging process, which is very annoying. I'm not 100% sure what the exact parameters are to reproduce this one, but if a process, let's say CURL, waits for a timeout or something and you press Ctrl+C, you should return to the remote system's prompt. But instead you get completely booted out of the whole SSH Session with the above error.

I guess this is similar to a 'Window not responding' under Windows, but with proxytunnel it results in an instant killing of the connection, even though just waiting 100ms or so would result in everything being ok...

Can't get proxytunnel to work

Hello,

I can't seem to get proxytunnel to work on my apache vhost. My remote server has an SSH daemon running on port 2234 and an apache on 80/443.

VHOST CONFIG

<VirtualHost *:443>
  ServerName connect.website.com

  SSLEngine On
  SSLCertificateFile /etc/ssl/cert.pem
  SSLCertificateKeyFile /etc/ssl/privkey.pem
  SSLCertificateChainFile /etc/ssl/fullchain.pem

  #HostnameLookups on
  ProxyRequests On
  ProxyVia on

  AllowCONNECT 2234 #SSH ON 2234

#  <Proxy *>
#    Order deny,allow
#    Deny from all
#  </Proxy>
#  <Proxy 127.0.0.1>
#    Order deny,allow
#    Allow from all
#  </Proxy>

  DocumentRoot /var/www/connect
</VirtualHost>

SSH CONFIG

Host hazcod
  ServerAliveInterval 30
  ProxyCommand proxytunnel -v -X -p proxy.company.com:3128 -P 'companyuser:companypass' -r connect.website.com:443 -d 127.0.0.1:2234 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

LOG

hazcod@django:~$ ssh hazcod
SSL local to remote proxy enabled
Local proxy proxy.company.com resolves to 2.xxx.xxx.xxx
Connected to proxy.companycom:3128 (local proxy)

Tunneling to connect.website.com:443 (remote proxy)
Communication with local proxy:
 -> CONNECT connect.website.com:443 HTTP/1.0
 -> Proxy-Authorization: Basic xxxxx=
 -> Proxy-Connection: Keep-Alive
 -> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)
 <- HTTP/1.1 200 Connection established

Tunneling to 127.0.0.1:2234 (destination)
Communication with remote proxy:
 -> CONNECT 127.0.0.1:2234 HTTP/1.0
 -> Proxy-Connection: Keep-Alive
 -> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)
error: Socket write error.

Any ideas? I think it's strange he is trying to do a CONNECT 127.0.0.1:2234 HTTP/1.0 instead of a SSH client connect.. Thanks.
Regards

how to build with latest patch/enhancement on RHEL/CentOS

The official build for RHEL6/7 doesn't work for years. It fails with following apache2 version 2.4.10 log:

[Wed Sep 20 12:45:23.516234 2017] [ssl:info] [pid 11207] [client 111.222.111.222:42386] AH02008: SSL library error 1 in handshake (server sample.com:443)
[Wed Sep 20 12:45:23.516330 2017] [ssl:info] [pid 11207] SSL Library Error: error:1408A10B:SSL routines:ssl3_get_client_hello:wrong version number
[Wed Sep 20 12:45:23.516358 2017] [ssl:info] [pid 11207] [client 111.222.111.222:42386] AH01998: Connection closed to child 0 with abortive shutdown (serversample.com:443)

But for the same setting and command, Debian 8 works perfectly.

I attempted to build my own but see no difference on RHEL except the HTTP/1.0 changed to HTTP/1.1

sudo yum -y install asciidoc xmlto rpm-build
wget https://github.com/proxytunnel/proxytunnel/archive/1.9.1.tar.gz
tar xf 1.9.1.tar.gz
cd proxytunnel-1.9.1/
make rpm
rpm -ivh ../proxytunnel-1.9.0-1.x86_64.rpm
proxytunnel -V
proxytunnel 1.9.0 (rev $) Copyright 2001-2008 Proxytunnel Project

Please let me know how to compile/build the latest code of proxytunnel for RHEL to solve the issue.

Proxytunnel -X gives Error - No Certificate Presented

Hello,

I am using the latest Proxytunnel 1.9.9 32-bit that I compiled from sources using Cygwin 32-bit.

This command works fine for me when I am in another situation and the local proxy is one I made myself however when it is not I get the below error. At the end it seems to connect HTTP 200 to the destination... my sshd server... but then the SNI hostname gets set to the remote proxy again and then it says: No Certificate Presented.

root.pem contains the root certificate of the trusted CA of Letsencrypt which I use to get my own certs.

E:\Proxytunnelv1.9.9-32bit>proxytunnel -v -X -C root.pem -p 192.168.423.45:3128 -N -P usr:pwd,
 -t A_DOMAIN -R remote_user:remote_pwd -r my.remote.proxy:443 -d 192.168.0.10:22,
 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
SSL local to remote proxy enabled
Build Type 1 NTLM Message : GOEMIFJJJJJJJJJJSSSSSSSSSSS
Connected to 192.168.423.45:3128 (local proxy)

Tunneling to my.remote.proxy:443 (remote proxy)
Communication with local proxy:
 -> CONNECT my.remote.proxy:443 HTTP/1.1
 -> Host: my.remote.proxy:443
 -> Proxy-Authorization: NTLM GOEMIFJJJJJJJJJJSSSSSSSSSSS
 -> Proxy-Connection: Keep-Alive
 -> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)
 <- HTTP/1.1 407 Proxy Access Denied

HTTP return code: 407 Proxy Access Denied
 <- Server: WebMarshal Proxy

 <- Content-Length: 0

 <- Proxy-Connection: keep-alive

 <- Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAGAAYADgAAAA

parse_type2: Signature matched
NTLM Got Domain: A_DOMAIN
NTLM Overriding domain: A_DOMAIN
NTLM Domain: A_DOMAIN
NTLM Got Challenge: 795EVH7552B4C92D
NTLM: MD4 of password is: F3BCDA8379EPMLSA7
DOMAIN: A_DOMAIN
USER: user.name
userdom is: 46004500520047004100
HMAC_MD5 of userdom keyed with MD4 pass is: 43DA09F
client_challenge is: B081
HMAC is: 39B877F7
 <- X-WebMarshal-RequestID: B968C538-C0OO

 <-


Tunneling to my.remote.proxy:443 (remote proxy)
Communication with local proxy:
 -> CONNECT my.remote.proxy:443 HTTP/1.1
 -> Host: my.remote.proxy:443
 -> Proxy-Authorization: NTLM TlRMTVNTUAADAAAA
 -> Proxy-Connection: Keep-Alive
 -> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)
 <- HTTP/1.1 200 Connection Established

 <- Via: 1.1 PS1905KLN

 <- X-WebMarshal-RequestID: 7CCB0769-KK

 <-

Set SNI hostname to my.remote.proxy

Tunneling to 192.168.0.10:22 (destination)
Communication with remote proxy:
 -> CONNECT 192.168.0.10:22 HTTP/1.1
 -> Host: 192.168.0.10:22
 -> Proxy-Authorization: Basic ZGFy
 -> Proxy-Connection: Keep-Alive
 -> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)
 <- HTTP/1.0 200 Connection Established

 <- Proxy-agent: Apache/2.4.25 (Raspbian)

 <-

Set SNI hostname to my.remote.proxy
No certificate presented

This works fine if the local proxy is one that I control.. I don't see that second: Set SNI hostname to my.remote.proxy or: No certificate presented

Is something in this local proxy blocking Proxytunnel? Any help would be very welcome.

Thank you

Flex

commit 4bac945fc78121277d3735ffb22ba83a64b91c16 to fix issue #57 is wrong

commit 4bac945 to fix #57 is wrong and proxytunnel is broken since this commit. SSL_set_tlsext_host_name() returns 1 on success or 0 in case of an error. Error codes like SSL_TLSEXT_ERR_OK, SSL_TLSEXT_ERR_ALERT_FATAL, SSL_TLSEXT_ERR_ALERT_WARNING and SSL_TLSEXT_ERR_NOACK are returned by the underlaying function SSL_CTX_set_tlsext_servername_callback() but not from SSL_set_tlsext_host_name() itself. My proposal to fix the issue is:

diff --git a/ptstream.c b/ptstream.c
index 7146862..101b2c8 100644
--- a/ptstream.c
+++ b/ptstream.c
@@ -341,13 +341,11 @@ int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg) {
 		message( "Set SNI hostname to %s\n", peer_host);
 	}
 	res = SSL_set_tlsext_host_name(ssl, peer_host);
-	if (res != SSL_TLSEXT_ERR_OK) {
-		unsigned long ssl_err = (res == SSL_TLSEXT_ERR_ALERT_WARNING ? SSL_TLSEXT_ERR_ALERT_WARNING : ERR_get_error());
-		message( "SSL_set_tlsext_host_name returned: %lu (0x%lx). "
-		         "TLS SNI error, giving up\n", ssl_err, ssl_err );
-		exit( 1 );
+	if (res != 1) {
+		message( "SSL_set_tlsext_host_name failed\n" );
+		goto fail;
 	}
-	
+
 	if ( SSL_connect (ssl) <= 0) {
         message( "SSL_connect failed\n");
         goto fail;

Missing Error Check in function SSL_connect()

Hi,
Function SSL_connect() returns the value of 0 and less than 0 are both on error. However , the return value of function SSL_connect() is not checked . See the following code:

line: 314

proxytunnel/ptstream.c

Lines 288 to 314 in f7831a2

ssl = SSL_new (ctx);
SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
SSL_set_wfd (ssl, stream_get_outgoing_fd(pts));
/* Determine the host name we are connecting to */
proxy_arg_len = strlen(proxy_arg);
if ((peer_host = malloc(proxy_arg_len + 1)) == NULL) {
message("Out of memory\n");
goto fail;
}
snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), proxy_arg[0] == '[' ? "[%%%zu[^]]]" : "%%%zu[^:]", proxy_arg_len - 1 );
if ( sscanf( proxy_arg, proxy_arg_fmt, peer_host ) != 1 ) {
goto fail;
}
/* SNI support */
if ( args_info.verbose_flag ) {
message( "Set SNI hostname to %s\n", peer_host);
}
res = SSL_set_tlsext_host_name(ssl, peer_host);
if (res < 0) {
message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n %u\n", res );
exit( 1 );
}
SSL_connect (ssl);

==================================================================================

We find the return value of this call been checked in openssl project with the version of openssl 1.1.2.
Such as in openssl/apps folder

line: 376, 377
ref: https://github.com/openssl/openssl/blob/1362190b1b786a87378e55e9a1c20c46b6b6a286/apps/s_time.c#L376-L387

line 376:    i = SSL_connect(serverCon);
line 377:    if (i <= 0) {
line 378:        BIO_printf(bio_err, "ERROR\n");
line 379:        if (verify_args.error != X509_V_OK)
line 380:            BIO_printf(bio_err, "verify error:%s\n",
line 381:                               X509_verify_cert_error_string(verify_args.error));
line 382:        else
line 383:            ERR_print_errors(bio_err);
line 384:        if (scon == NULL)
line 385:             SSL_free(serverCon);
line 386:        return NULL;
line 387:    }

Chi Li, Zuxing Gu, Jiecheng Wu

Issue in ProxyTunnel Behaviour on HTTPS proxy

Hello,
Firstly, I would like to thank proxytunnel owner and contributor for this wonderful tool!

Few years ago, it was working like a charm, but after lot of updates (Apache, ssh), it stopped to work:

To explain the issue: If I do a "openssl s_client -connect" on the my https server on port 443 with the following command

CONNECT localhost:22 HTTP/1.0
Proxy-Connection: Keep-Alive

I get the response "HTTP/1.0 200 Connection Established" as expected.

But if I do the following
proxytunnel.exe -v -E -p www.mywebsite.com:443 -d localhost:22
I get

Tunneling to localhost:22 (destination)
Communication with local proxy:
 -> CONNECT localhost:22 HTTP/1.0
 -> Proxy-Connection: Keep-Alive
error: Socket write error.

As you can see, I copied the same Connect and proxy-connection instructions in the openssl shell and I got a different result.
My ProxyTunnel version is 1.9.0 (rev 224) and it's the lastest one.
I used the compiled binary, and I'm pretty affraid that someone will ask me to get the repo and do the compilation... :(

Would you know what could be the problem? (I'm pretty sure my server-side apache configuration is good)
Thanks & regards

Merge refactored code from Devin Nate

@devinnate contributed refactored code and we like to merge/integrate this in the current codebase.

Technically speaking, we required an ultra-reliable (in terms of ability to connect / autodetect) command for ssh's ProxyCommand functionality. We needed HTTP CONNECT supporting no-authentication, basic auth, and NTLM auth (versions ntlmv1, ntlmv2, and ntlmv1 wih v2 enhancements), including auto-detection. We needed ssl tunneling support. Future looking, we needed flexibility to add SOCKS if needed and tunneling over http (so encoding ssh as get/post, or similar technique).

To accomplish this, we started with proxytunnel, integrated cntlm to it, and wrote a bunch of our own code. We've removed all the standalone capabilities and double hop processing (mostly because double hop + autodetect made life amazingly complicated), and probably a bunch of other things if it made it more complicated than we wanted.

This integrated code will be released as v2.0.

Allow defining logging location

I run proxytunnel as a systemd service and it works absolutely amazingly.

I do want to separate the logs for it out to another log file, as it's a little chatty. It appears as if there's no way to define it, and there's logic built into the application in which it will only log to syslog.

Two asks:

  1. Can we add an option to set a logging file path?
  2. Can we remove any special chars that are added as well?

Invalid path name error

I want to use proxytunnel in Windows 10 CMD with the below command:

C:\proxytunnel>proxytunnel.exe -q -p mywebsite.com:81 -d 127.0.0.1:22

But I got this error. I Google it but didn't find anything.

0 [main] proxytunnel (10136) dll_list::form_ntname: WARNING: invalid path name '\??'
510 [main] proxytunnel (10136) C:\proxytunnel\proxytunnel.exe: *** fatal error - add_item ("\??", "/", ...) failed, errno 22
Stack trace:
Frame        Function    Args
000FFFF8630  00180062835 (00180296FE2, 00180272E41, 0000000003F, 000FFFF8B10)
000FFFF8B60  001800488F2 (00000000000, 00180020010, 000FFFFABB6, 000FFFF9BB0)
000FFFF9B70  00180048931 (000FFFF9BB0, 00000000016, 0000000003F, 00000000001)
000FFFF9C00  001800E5D0D (00000000000, 001800D9350, 000FFFFCBD0, 000FFFFCC50)
000FFFFCC70  001801364E5 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFCCE0  00180048F75 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFCDA0  0018004794A (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFCE50  00180047A0C (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace

Add default test-cases and improve errors

It would be very useful to test the various use-cases before releasing proxytunnel, and also add specific error conditions for various error conditions:

  • local proxy does not exist (unresolvable)
  • local proxy exists but does not answer (tcp timeout)
  • local proxy does not talk HTTP
  • local proxy is not a proxy (does not accept CONNECT)
    • remote proxy does not exist (unresolvable)
    • remote proxy exists but does not answer (tcp-timeout)
  • remote proxy does not talk HTTP
  • remote proxy is not a proxy (does not accept CONNECT)

There are various approaches to this, but since it requires the need for some infrastructure to test various authentication methods it may not be as easy as we would like this to be. But at least the common functionality should not be that hard.

Error: HTTP/1.1 403 Certificateincident

Hi.

I'm using this command and I'm getting this error:

D:\proxytunnel-1.9.7-cygwin>proxytunnel.exe -E -p XXX.XXX.XXX.XXX:443 -d 127.0.0.1:22 -v -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)\n"
Connected to XXX.XXX.XXX.XXX:443 (local proxy)

Tunneling to 127.0.0.1:22 (destination)
Communication with local proxy:
-> CONNECT 127.0.0.1:22 HTTP/1.1
-> Host: 127.0.0.1:22
-> Proxy-Connection: Keep-Alive
-> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)\n
<- HTTP/1.1 403 Certificateincident

HTTP return code: 403 Certificateincident
<- Content-Type: text/html

<- Cache-Control: no-cache

<- Content-Length: 4392

<- Proxy-Connection: Keep-Alive

<-
.axX.a►

D:\proxytunnel-1.9.7-cygwin>

On apache default-ssf.conf, I've this configured.

SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

Anyone knows what can be cause this error?
I'm trying this behind a McAfee Web Gateway, did you guys think that web gateway is blocking self-signed certificates or something similar?

Kind regards.

Incorrect use of SSL_set_tlsext_host_name

Here the SSL_set_tlsext_host_name's return value is checked for being equal to SSL_TLSEXT_ERR_OK (=0) as a sign of success, while the manpage says that it returns 0 or 1 and 1 means success:

RETURN VALUES
       SSL_CTX_set_tlsext_servername_callback() and
       SSL_CTX_set_tlsext_servername_arg() both always return 1 indicating
       success.  SSL_set_tlsext_host_name() returns 1 on success, 0 in case of
       error.

Add proxy bouncing authentication support with new syntax

The current syntax for proxy bouncing authentication is less than optimal and would not work for multi-level proxy bouncing. That is why we propose to use a syntax like:

proxytunnel -p user@local-proxy:port -r user@remote-proxy:port -d %h:%p

or when using the password on the command-line, use:

proxytunnel -p username:password@local-proxy:port -r username:password@remote-proxy:port -d %h:%p

This does require some thought for using environment variables and/or a password file.

Proxytunnel to a HTTP Proxy gives: HTTP 400 error

Hello,

I am trying to use Proxytunnel to tunnel through a forward proxy I have set up on my Apache web server to “CONNECT” to my sshd server and hence ssh over Port 80.

This works when I am inside my LAN and my client, the Pi running apache and SSHD are on the same network. However it does not work if I simulate the client being outside my LAN by connecting to a Wifi hotspot from my phone… in this case I get a HTTP 400 error: Your browser sent a malformed request.

I am using a Windows version of Proxytunnel v1.9.7

Here is my HTTP Apache forward proxy on port 80:

<VirtualHost _default_:80>
            DocumentRoot /var/www
            ServerName example.com

            ErrorLog /var/log/apache2/ssh-proxy_error_log
            CustomLog /var/log/apache2/ssh-proxy_access_log combined
            LogLevel debug

            ProxyRequests on
            ProxyVia block
            ProxyBadHeader Ignore
            AllowCONNECT 22

            <Proxy *>
               Require all denied
            </Proxy>
            <Proxy 192.168.1.124>
               Require all granted
            </Proxy>
</VirtualHost>

I test the connection from inside my LAN from a windows command line with this command:

# proxytunnel -v -p example.com:80 -d 192.168.1.124:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

And I get this output on the command line:

C:\Users\Me>proxytunnel -v -p example.com:80 -d 192.168.1.124:22
Local proxy example.com resolves to 192.168.1.124
Connected to example.com:80 (local proxy)

Tunneling to 192.168.1.124:22 (destination)
Communication with local proxy:
-> CONNECT 192.168.1.124:22 HTTP/1.1
-> Host: 192.168.1.124:22
-> Proxy-Connection: Keep-Alive
<- HTTP/1.0 200 Connection Established

<- Proxy-agent: Apache

<-


Tunnel established.
SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u3

Happy Days. However, now I disconnect from my LAN and connect to a Wifi hotspot created on my Phone to simulate being outside my LAN and this time when I repeat the exact same command above I get:

C:\Users\Me>proxytunnel -v -p example.com:80 -d 192.168.1.124:22
Local proxy example.com resolves to XX.XX.XX.XX <<-- external IP of my home router
Connected to example.com:80 (local proxy)

Tunneling to 192.168.1.124:22 (destination)
Communication with local proxy:
-> CONNECT 192.168.1.124:22 HTTP/1.1
-> Host: 192.168.1.124:22
-> Proxy-Connection: Keep-Alive
<- HTTP/1.1 400 Bad request

HTTP return code: 400 Bad request
<- Date: Mon, 14 May 2018 19:32:27 GMT

<- Content-Type: text/html

<- Content-Length: 1270

<-

I looked at the HTTP headers of the Client request and Server response in Wireshark and I can't see what the problem is there. When I get the Http 400 error nothing is logged at all to my apache logs so I wonder how can I debug this? I even tried making the latest Proxytunnel 1.9.9 on Linux and ran it from there too and got the same result.

Any idea why this is?

Thank you,

Flex

MaxKeepAliveRequests in apache2 is not respected by proxytunnel

I want to make proxytunnel re-establishes connection for a couple of hours in order to avoid long running http connection. The reason is my company's firewall detects the suspected long running connections and blacklist the client nodes.

B.T.W. It looks like this project has no active maintainers any more. It's really pity for such a great software.

Provide new Windows binaries

We do not have the infrastructure or access to Windows systems, but various users have requested new Windows build.

Connection fails through nginx: 400 Bad Request

I am running nginx with the third party http_proxy_connect module on FreeBSD.
The ssh client setup is exactly like in the README:

host foo
        ProxyCommand /usr/local/bin/proxytunnel -p {host-name}:8080 -d localhost:443

nginx config is exactly like described in the README.

The session fails:

$ ssh foo
Via xx.xx.xx:8080 -> localhost:443
HTTP return code: 400 Bad Request
Fssh_kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

nginx writes this line into access.log:

192.168.5.1 - - [03/May/2023:23:13:12 -0700] "CONNECT localhost:443 HTTP/1.1" 400 255 "-" "-"

"400 Bad Request" is returned.

While looking at the kernel log on the client I see that it first connects through https, then it closes the socket, and then it connects again and sends the CONNECT command through http. Why does it need to connect through http?

When browser connects to the same host via https it sees the default nginx page saying that connection is successful.

What might be wrong?

Direct tunnel (no proxy)

Is there any way to make a direct connection to a remote stunnel service?

This syntax does not work with proxytunnel 1.10.20210128 (Windows 10 x64):

>proxytunnel -v -d 111.122.133.144:443 -e
SSL enabled
error: failed to connect to local proxy: [125] Cannot assign requested address

If not possible, coould you consider this as a new feature?

Use proxytunnel with Openvpn without ssh

Hi All,
thanks for your great work!

I have used proxytunnel to established a tunnel form a local http proxy and remote http proxy to connect to an openvpn server. Command is something like that:
proxytunnel -v -p my-local-proxy:3128 -R proxy-username:proxy-password -r my-remote-proxy:80 -d my-remote-openvpn-server:444

Tunnel is established properly, but now i would like to use an openvpn-client to connect to openvpn-server through this tunnel. I have tried to use -a option to run proxytunnel as standalone daemon, and i have used socks-proxy configuration options on openvpn, but unfortunately with no success.

Any advice to accomplish this task without establish an ssh tunnel?

Optionally accept alternative default CA file and/or directory path at compile time

Currently, proxytunnel looks by default for a CA certificate file in /etc/ssl/certs, but on current versions of macOS, that directory is always empty. This has the effect that, to use proxytunnel on macOS (as shipped with Homebrew, for example), one must always specify a path using --cacert at runtime. To address this, I've drafted a small patch to allow specifying a different default at compile time.

If a PR with a patch to this effect would be welcome, I'd be glad to open one based on my test fork, here. I've compiled this and verified it works on macOS Catalina as a drop-in replacement for the current version proxytunnel provided through Homebrew.

For example, I can use the resulting binary for an SSH/HTTPS tunnel, … after uncommenting the existing DARWIN and new DARWIN, continued… options in the Makefile and compiling. This lets me replace lines in scripts which currently look like:

proxytunnel --quiet --encrypt-proxy --cacert="$(/usr/local/opt/openssl/bin/openssl version -d | cut -d'"' -f2)/cacert.pem" --proxy=some-server.invalid:443 --dest=127.0.0.1:22

with:

~/Documents/GitHub/proxytunnel/proxytunnel --quiet --encrypt-proxy --proxy=some-server.invalid:443 --dest=127.0.0.1:22

(Of course, the explicit binary path would no longer be needed in the final version.)

Feedback welcome. Thoughts?

Make new release

It would sure be nice if you could put out a new release tag at some point. Linux Distributions don't pick up any new version of proxytunnel, unless that exists (e.g.: fedora and gentoo are on 1.9.1 or even 1.9.0), and so we miss some nice new stuff like SNI support for HTTPS, TLS improvements and some fixes.

Usage on Windows 11

I would really like to use this on Windows 11. I'm getting the following error.

...
debug1: Executing proxy command: exec C:\\msys64\\home\\ericc\\repos\\proxytunnel\\bin\\proxytunnel.exe -E -p  somewhere:443 -d 127.0.0.1:22
debug3: spawning "C:\\msys64\\home\\ericc\\repos\\proxytunnel\\bin\\proxytunnel.exe" -E -p somewhere:443 -d 127.0.0.1:22 as subprocess
debug3: w32_getpeername ERROR: not sock :2
debug1: identity file C:\\Users\\ericc/.ssh/id_rsa type 0
debug3: Failed to open file:C:/Users/ericc/.ssh/id_rsa-cert error:2
debug3: Failed to open file:C:/Users/ericc/.ssh/id_rsa-cert.pub error:2
debug3: failed to open file:C:/Users/ericc/.ssh/id_rsa-cert error:2
debug1: identity file C:\\Users\\ericc/.ssh/id_rsa-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_for_Windows_8.6
Via somewhere:443 -> 127.0.0.1:22
SSL_set_tlsext_host_name returned: 1 (0x1). TLS SNI error, giving up
kex_exchange_identification: Connection closed by remote host

My config looks something like this.

Host somewhere
  HostName somewhere
  ProxyCommand C:\msys64\home\ericc\repos\proxytunnel\bin\proxytunnel.exe -E -p somewhere:443 -d 127.0.0.1:22
  Port 443
Host *
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_rsa
  ServerAliveInterval 100
  StrictHostKeyChecking no
  User ehansen

This config works on WSL2 and Ubuntu 22.04.2 LTS.

The error seems to originate around here,

proxytunnel/ptstream.c

Lines 339 to 349 in 16500d2

/* SNI support */
if ( args_info.verbose_flag ) {
message( "Set SNI hostname to %s\n", peer_host);
}
res = SSL_set_tlsext_host_name(ssl, peer_host);
if (res != SSL_TLSEXT_ERR_OK) {
unsigned long ssl_err = (res == SSL_TLSEXT_ERR_ALERT_WARNING ? SSL_TLSEXT_ERR_ALERT_WARNING : ERR_get_error());
message( "SSL_set_tlsext_host_name returned: %lu (0x%lx). "
"TLS SNI error, giving up\n", ssl_err, ssl_err );
exit( 1 );
}
.

Proxytunnel to a HTTPS Proxy gives: Connection timed out

Hello,

I am trying to ssh over port 443 from work to my raspberry Pi at home using Proxytunnel and a forward proxy I set up on my own Apache server at home.

I use an insecure Public open access Wifi network at work that does not have a work proxy to go through and the Admin people tell me ssh is not blocked over port 443. I want to use this Port to also get secure access to a personal web server so I don't want to have my SSH server listen on Port 443.

I am using a Windows version of Proxytunnel v1.9.7 but got the same result with v1.9.9 and also the same result with v1.9.9 compiled for Linux OS.

Here is the HTTPS Forward Proxy Virtualhost on my Apache

<VirtualHost _default_:443>
    DocumentRoot /var/www
    ServerName example.com
    
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    
    LogLevel debug
    CustomLog /var/log/apache2/ssh-proxy_access_log combined
    ErrorLog /var/log/apache2/ssh-proxy_error_log
    
    ProxyRequests on
    ProxyVia block
    ProxyBadHeader Ignore

    AllowCONNECT 22	
    <Proxy *>
        Require all denied
    </Proxy>
    <Proxy 192.168.1.124>
        Require all granted
    </Proxy>
</VirtualHost>

I test the connection from windows command line with this command:

# proxytunnel -v -E -p example.com:443 -d 192.168.1.124:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

This is what I get back in the command window, client side:

G:\SSH Tools\progs>proxytunnel -v -E -p example.com:443 -d 192.168.1.124:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
SSL client to proxy enabled
Local proxy example.com resolves to XX.XX.XX.XX <-- external IP address of my router
error: connect() failed: [116] Connection timed out

This is what I see in the Apache logs:
-- ssh-proxy_access_log
Work-IP-address - - [13/May/2018:09:36:10 +0100] "CONNECT 192.168.1.124:22 HTTP/1.1" 200 3635 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

-- ssh-proxy_error_log

AH01992: SSL library error 1 reading data SSL Library Error: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
proxy_util.c(3831): (20014)Internal error (specific information not available): [client Work-IP-address:41491] AH03308: ap_proxy_transfer_between_connections: error on client - ap_get_brigade

When I try this command from inside my LAN or also from a Wifi hotspot I create from my phones 4G data then it works and I can get an ssh session going in Putty. But yet I get a timeout from the Public Wifi network at my work?

Looking at the ssh-proxy_error_log it seems the issue is with my Apache Proxy and probably not a firewall issue at work. Do I need to turn off SSL3 encryption in Apache maybe?

Any help you could provide would be much appreciated !

Flex

Make a v1.9.1 release

Since the release of proxytunnel v1.9.0 there have been many changes, a new v1.9.1 release would bring these to users. The current CHANGES file hints for a v1.9.1 release including:

  • Switch to HTTP/1.1 commands, so we can tunnel over JoikuSpot's which
    don't understand http/1.0 command (Mark Janssen)
  • NTLMv2 fixes by Giulio Galante [email protected]
  • Read http_proxy before HTTP_PROXY env var

But a log of the changes reveals a few more.

Setting up a web proxy to test Proxytunnel -r Remote Proxy feature

Hello,

Question:

How do I configure a proxy Virtualhost on Apache2 so that Proxytunnel can tunnel through it making use of its -r remote proxy feature?
Does the "local proxy" need to be a reverse proxy?
How is the "local proxy" configured to give access to any client and proxy to a remote proxy that is not hard-coded in to the Virtualhost but defined in the Proxytunnel command using the -r "remote proxy" argument.

Here is what I have got working:

I use Proxytunnel to tunnel through a forward proxy I have set up on my Apache web server to “CONNECT” to my sshd server and hence ssh over Port 80.

Here is my HTTP Apache forward proxy on port 80:

<VirtualHost _default_:80>
            DocumentRoot /var/www
            ServerName example.com

            ErrorLog /var/log/apache2/ssh-proxy_error_log
            CustomLog /var/log/apache2/ssh-proxy_access_log combined
            LogLevel debug

            ProxyRequests on
            ProxyVia block
            ProxyBadHeader Ignore
            AllowCONNECT 22

            <Proxy *>
               Require all denied
            </Proxy>
            <Proxy 192.168.1.124>
               Require all granted
            </Proxy>
</VirtualHost>

I test the connection from a windows command line with this command:

# proxytunnel -v -p example.com:80 -d 192.168.1.124:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

And I get this output on the command line:

C:\Users\Me>proxytunnel -v -p example.com:80 -d 192.168.1.124:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
Local proxy example.com resolves to 192.168.1.124
Connected to example.com:80 (local proxy)

Tunneling to 192.168.1.124:22 (destination)
Communication with local proxy:
-> CONNECT 192.168.1.124:22 HTTP/1.1
-> Host: 192.168.1.124:22
-> Proxy-Connection: Keep-Alive
<- HTTP/1.0 200 Connection Established

<- Proxy-agent: Apache

<-

Tunnel established.
SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u3

I have access to two Raspberry Pis set up in two different geographical locations. I am trying to understand more about how Proxytunnel works and also to learn more about web server configuration.

How do I set up a Virtualhost on either Pi so I can make this command work:

# proxytunnel -v -p local_proxy:port -r remote_proxy:port -d destination_hostname:port -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

Does the Local proxy need to be a reverse proxy? How is it configured to give access to any ip address and forward to the hostname and port defined in the -r argument of the Proxytunnel command?

I guess what I'm really asking is: "How are Proxies configured so Proxytunnel can tunnel through them?"

Flex

Add multi-level proxy bouncing support with new syntax

We would like to implement multi-level bouncing support so that you can use more than one proxy-server (e.g. using a friend's proxy server to access your own proxy server). The new syntax for this would look like:

proxytunnel -p local-proxy:port -r remote-proxy1:port1 -r remote-proxy2:port2 -d %h:%p

Proxytunnel does not match -p <hostname> to ServerName in Apache Virtualhost over HTTP

Hello,

From my testing Proxytunnel 1.9.9 does not handle SNI correctly when proxying to a HTTP forward proxy.. whatever hostname is provided for the local proxy apache processes the default Virtualhost.

At the end of Issue #30 it was suggested to use the Proxytunnel -H "host: hostname" argument to supply a hostname so that the webserver will direct processing to the correct Virtualhost server side. My testing shows that this is not the case.

My Virtualhost that defines a http Proxy is like this:

<VirtualHost _default_:80>
	ServerName api.example.com
	DocumentRoot /var/www/html

	LogLevel debug
	ErrorLog /var/www/myproxy/logs/http-proxy-error.log
	CustomLog /var/www/myproxy/logs/http-proxy-access.log combined
..
..
</VirtualHost>

I also have another Virtualhost that defines a simple website on Port 80 like this:

<VirtualHost _default_:80>
	
	ServerName example.com
	ServerAlias www.example.com
	
	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/appleloli

	ErrorLog /var/www/mysite/logs/http-error.log
	CustomLog /var/www/mysite/logs/http-access.log combined

</VirtualHost>

If I try this Proxytunnel command:

proxytunnel -v -P flex:pwd -p example.com:80 -d 192.168.0.10:22

You would think it shouldn't work because I have a ServerName: example.com in a Virtualhost that defines no Proxy. However I do get the OpenSSH banner.

Nothing is logged in the http-access.log or http-error.log

This is what is logged in http-proxy-access.log
my.public.ip.addr - flex [28/May/2018:19:04:09 +0100] "CONNECT 192.168.0.10:22 HTTP/1.1" 200 119 "-" "-"

This is what is logged in http-proxy-error.log

[Mon May 28 19:04:09.638046 2018] [core:debug] [pid 23337:tid 3018847280] vhost.c(1172): [client my.public.ip.addr:53606] AH02417: Replacing host header 'example.com' with host '192.168.0.10:22' given in the request uri
[Mon May 28 19:04:09.638746 2018] [authz_core:debug] [pid 23337:tid 3018847280] mod_authz_core.c(809): [client my.public.ip.addr:53606] AH01626: authorization result of Require user flex: denied (no authenticated user yet)
[Mon May 28 19:04:09.638907 2018] [authz_core:debug] [pid 23337:tid 3018847280] mod_authz_core.c(809): [client my.public.ip.addr:53606] AH01626: authorization result of <RequireAny>: denied (no authenticated user yet)
[Mon May 28 19:04:09.642679 2018] [authz_core:debug] [pid 23337:tid 3018847280] mod_authz_core.c(809): [client my.public.ip.addr:53606] AH01626: authorization result of Require user flex: granted
[Mon May 28 19:04:09.642899 2018] [authz_core:debug] [pid 23337:tid 3018847280] mod_authz_core.c(809): [client my.public.ip.addr:53606] AH01626: authorization result of <RequireAny>: granted
[Mon May 28 19:04:09.643503 2018] [proxy:debug] [pid 23337:tid 3018847280] mod_proxy.c(1228): [client my.public.ip.addr:53606] AH01143: Running scheme 192.168.0.10 handler (attempt 0)
[Mon May 28 19:04:09.643678 2018] [proxy_connect:debug] [pid 23337:tid 3018847280] mod_proxy_connect.c(201): [client my.public.ip.addr:53606] AH01019: connecting 192.168.0.10:22 to 192.168.0.10:22

It looks like Apache is seeing the correct hostname header - example.com - without needing to use the -H "host: hostname" argument at all. Yet the "wrong" Virtualhost is selected by Apache.

I tried the suggestion to use the Proxytunnel -H "host: hostname" argument like this:

proxytunnel -v -P flex:pwd -p example.com:80 -d 192.168.0.10:22 -H "Host: api.example.com"

What should be the expected result?

If SNI works properly with Proxytunnel and since I have a Virtualhost (that does not define any proxy) with ServerName: example.com it should match with that and I shouldn't get any connection to my sshd server.

However I DO did get a connection to my sshd server. Why? Maybe the suggestion to add a host name using the header -H option worked out? I added the -H "Host: api.example.com" argument so maybe this is what apache sees and therefore selects the Proxy Virtualhost that has ServerName api.example.com in it?

I don't think this is what is happening behind the scenes:

This is logged to http-proxy-access.log
my.public.ip.addr - flex [28/May/2018:18:44:43 +0100] "CONNECT 192.168.0.10:22 HTTP/1.1" 200 119 "-" "-"
This is logged to http-proxy-error.log

[Mon May 28 18:44:43.325731 2018] [core:debug] [pid 23338:tid 2993681456] vhost.c(1172): [client my.public.ip.addr:53516] AH02417: Replacing host header 'example.com, api.example.com' with host '192.168.0.10:22' given in the request uri
[Mon May 28 18:44:43.326293 2018] [authz_core:debug] [pid 23338:tid 2993681456] mod_authz_core.c(809): [client my.public.ip.addr:53516] AH01626: authorization result of Require user flex: denied (no authenticated user yet)
[Mon May 28 18:44:43.326453 2018] [authz_core:debug] [pid 23338:tid 2993681456] mod_authz_core.c(809): [client my.public.ip.addr:53516] AH01626: authorization result of <RequireAny>: denied (no authenticated user yet)
[Mon May 28 18:44:43.329849 2018] [authz_core:debug] [pid 23338:tid 2993681456] mod_authz_core.c(809): [client my.public.ip.addr:53516] AH01626: authorization result of Require user flex: granted
[Mon May 28 18:44:43.330024 2018] [authz_core:debug] [pid 23338:tid 2993681456] mod_authz_core.c(809): [client my.public.ip.addr:53516] AH01626: authorization result of <RequireAny>: granted
[Mon May 28 18:44:43.330266 2018] [proxy:debug] [pid 23338:tid 2993681456] mod_proxy.c(1228): [client my.public.ip.addr:53516] AH01143: Running scheme 192.168.0.10 handler (attempt 0)
[Mon May 28 18:44:43.330429 2018] [proxy_connect:debug] [pid 23338:tid 2993681456] mod_proxy_connect.c(201): [client my.public.ip.addr:53516] AH01019: connecting 192.168.0.10:22 to 192.168.0.10:22

It seems that adding the -H "Host: api.example.com" argument to Proxytunnel just concatenates the local proxy host name and the host name provided in the additional header argument and this combination is what apache sees as the hostname.

In the first test above Apache2 must be seeing: "example.com" as the host header and in the second test apache sees: "example.com, api.example.com" as the host header... in both cases the default virtualhost is selected.

If I don't define the proxy in the default virtualhost then it would never work.

I haven't fully tested but recently a fix was merged #23 that fixes SNI handling. It may be that this works with https only?

Any comments or corrections gratefully received.

Flex

certificate/key support for auth

I have configured on HTTS server requirement for client certificate for authentication.
Without a client certificate, HTTPS servers refuse connections.
I want to specify certificate and key in proxytunnel options but not see such options.
Could you add options for the client certificate key?

I expecting use command like

proxytunnel -v -E \
  --client-cert my_cert.pem \
  --client-key my_key.pem \
  -p proxy.example.com:3129 \
  -d ifconfig.me:80

Update sourceforge page to link to github

Hello,

proxytunnel was flagged as outdated in Arch Linux and pointed to this repository, but I can't find anything on the old sourceforge page that links to this repository to verify authenticity.

Can you add a link or a news post on the old page that the repository has been moved here officially?

Missing Error Check in function SSL_new()

Hi,
Function SSL_new() returns a pointer to an SSL object on success or NULL on error. However, the function SSL_new() didn't check the return value is NULL or not, before passing the return value as an argument to both the function SSL_set_rfd() and SSL_set_wfd(). See the following details.

proxytunnel/ptstream.c

Lines 288 to 291 in f7831a2

ssl = SSL_new (ctx);
SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
SSL_set_wfd (ssl, stream_get_outgoing_fd(pts));

Chi Li, Zuxing Gu, Jiecheng Wu

Patch: parse_cmdline: could not find your proxy hostname/ip does not refer to a dns resolution issue

Currently,

$ proxytunnel -p proxy.server1.tld -d www.server2.tld:port

results in the following error message:

parse_cmdline: could not find your proxy hostname/ip (proxy.server1.tld)

IMHO, such an error message can be associated by the user with a dns resolution issue. Which is misleading here.
The patch follows the manual page to explicitly mentions the required specification of the proxy port too. And explicitly mentions an expected pattern.

--- a/cmdline.c	2022-05-26 19:29:32.621516175 +0000
+++ b/cmdline.c	2022-05-27 21:20:21.420538767 +0000
@@ -581,7 +581,7 @@
 			args_info->proxyhost_given = 1;
 			args_info->proxyport_given = 1;
 		} else {
-			message( "parse_cmdline: could not find your proxy hostname/ip (%s)\n", args_info->proxy_arg );
+			message( "parse_cmdline: specified proxy hostname/ip:port (%s) does not fit expected pattern\n", args_info->proxy_arg );
 			missing_required_options++;
 		}
 	}

It could be a better approach would be to have the code more ditsinctly handle the proxy hostname/ip and the proxy port. Something along the lines of

    parse the proxy hostname/ip
    if there is a problem, output an error message
    parse the proxy port
    if there is a problem, output a different error message

But I have no time for that.
I have not looked for the error messages when parsing the -r remote, 2nd, proxy. Or the -d destination host. It could be these messages are similar to the message above.

NTLM based authentication is broken on 64bit machines

Structure security_buf_t, ntlm_type1, ntlm_type2, ntlm_type3 and blob, defined in ntlm.h, are using unsigned long entries. All of this entries must be 32bit. My proposal to fix this, is to change all types in this structures to standard int types like uint8_t, uint16_t, uint32_t and uint64_t:

diff --git a/ntlm.h b/ntlm.h
index 01a6434..3d91c8d 100644
--- a/ntlm.h
+++ b/ntlm.h
@@ -18,6 +18,9 @@
  */
 
 /* ntlm.h */
+
+#include <stdint.h>
+
 void build_type1();
 int parse_type2(unsigned char *buf);
 void build_type3_response();
@@ -55,53 +58,53 @@ extern char ntlm_type3_buf[4096];
 
 
 typedef struct {
-	unsigned short	length;
-	unsigned short	space;
-	unsigned long	offset;
+	uint16_t	length;
+	uint16_t	space;
+	uint32_t	offset;
 } security_buf_t;
 
 typedef struct {
-	unsigned char	signature[8];
-	unsigned long	message_type;
-	unsigned long	flags;
+	uint8_t	signature[8];
+	uint32_t	message_type;
+	uint32_t	flags;
 	security_buf_t	domain;
 	security_buf_t	workstation;
 } ntlm_type1;
 
 typedef struct {
-	unsigned char	signature[8];
-	unsigned long	message_type;
+	uint8_t	signature[8];
+	uint32_t	message_type;
 	security_buf_t	target_name;
-	unsigned long	flags;
-	unsigned char	challenge[8];
-	unsigned long	context1;
-	unsigned long	context2;
+	uint32_t	flags;
+	uint8_t	challenge[8];
+	uint32_t	context1;
+	uint32_t	context2;
 	security_buf_t	target_info;
-	unsigned char	data_start;
+	uint8_t	data_start;
 } ntlm_type2;
 
 typedef struct {
-	unsigned char	signature[8];
-	unsigned long	message_type;
+	uint8_t	signature[8];
+	uint32_t	message_type;
 	security_buf_t	LM_response;
 	security_buf_t	NTLM_response;
 	security_buf_t	domain;
 	security_buf_t	user;
 	security_buf_t	workstation;
-	unsigned char	session[8];
-	unsigned long	flags;
-	unsigned char	pad[8];
+	uint8_t	session[8];
+	uint32_t	flags;
+	uint8_t	pad[8];
 
 } ntlm_type3;
 
 typedef struct {
-	unsigned char	digest[16];
-	unsigned long	signature;
-	unsigned long	reserved;
-	unsigned long long	timestamp;
-	unsigned char	client_challenge[8];
-	unsigned long	unknown;
-	unsigned long	data_start;
+	uint8_t	digest[16];
+	uint32_t	signature;
+	uint32_t	reserved;
+	uint64_t	timestamp;
+	uint8_t	client_challenge[8];
+	uint32_t	unknown;
+	uint32_t	data_start;
 } blob;
 
 // vim:noexpandtab:ts=4

Patch: SSL_set_tlsext_host_name() > 0 indicates a problem. Not < 0.

Consider lines 343-347 of ptstream.c:

   res = SSL_set_tlsext_host_name(ssl, peer_host);
   if (res < 0) {
       message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n %u\n", res );
       exit( 1 );
   }

But man SSL_set_tlsext_host_name shows exit codes of the form SSL_TLSEXT_ERR_*. By openssl/tls1.h, these have values >= 0.
Following the openssl-bio-fetch.tar.gz example from the openssl wiki, I suggest:

--- a/ptstream.h	2021-01-28 22:12:52.000000000 +0000
+++ b/ptstream.h	2022-05-26 13:29:54.199452530 +0000
@@ -21,6 +21,7 @@
 
 #ifdef USE_SSL
 #include <openssl/crypto.h>
+#include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
 #include <openssl/ssl.h>

and

--- a/ptstream.c	2021-01-28 22:12:52.000000000 +0000
+++ b/ptstream.c	2022-05-26 17:32:04.192694338 +0000
@@ -333,8 +333,10 @@
 		message( "Set SNI hostname to %s\n", peer_host);
 	}
 	res = SSL_set_tlsext_host_name(ssl, peer_host);
-	if (res < 0) {
-		message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n  %u\n", res );
+	if (res != SSL_TLSEXT_ERR_OK) {
+		unsigned long ssl_err = (res == SSL_TLSEXT_ERR_ALERT_WARNING ? SSL_TLSEXT_ERR_ALERT_WARNING : ERR_get_error());
+		message( "SSL_set_tlsext_host_name returned: %lu (0x%lx). "
+		         "TLS SNI error, giving up\n", ssl_err, ssl_err );
 		exit( 1 );
 	}

As far as I can tell, there are no other occurences of SSL_set_tlsext_host_name() in the code.

No support for proxy with username and password

Hello,

Most software today understand the following http_proxy environment variable :
http://username:password@host:port/

Proxytunnel doesn't, which make it incompatible with this variable.
Worst, the format is not even recognize to extract only the host and port, so we cannot just add the proxyuser and proxypassword environment variable to make it work.

On this file https://github.com/proxytunnel/proxytunnel/blob/master/cmdline.c#L490
We should juste change the logic to parse it this way :

if contains @
cut the string in 2 part
part1 = user[:password]
part2 = host[:port]
else
use current code
endif

And to apply the same rule that you are using in your code.

Do you think it will be possible ?
Do you need me to do the code and do a pull request ?
I'm not familiar with c++ at all, so I might not be very efficient, neither without bugs...

Best regards,
Pierre

Max length for proxy password?

I'm using proxytunnel 1.9.0 (rev 242) and it's silently trimming proxy passwords down to 24 characters.

Is this expected behaviour?

I couldn't see this in the RFCs, and I'm wondering if it could even be a buffer overflow.

How to setup stunnel with proxytunnel?

I have the current situation:

client ---/firewall/----> [ Stunnel / HTTP Server / SSH Server ]

I want to connect from client to ssh server, but I cannot seem to get it right, as I found no examples of stunnel with proxytunnel to server.
I'm using Apache as a proxy; if I use it directly on HTTP layer it works perfectly, but when I try to use SSL things get ugly.

my stunnel.conf:

syslog = yes
cert = /etc/stunnel/stunnel.pem
[https-proxy]
accept = 443
connect = 127.0.0.1:80

my proxycommand:
ProxyCommand proxytunnel -e -v -p SSH-SERVER:80 -d %h:%p -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"'

of course I'm connecting via port 443:
ssh user@server -p 443

The firewall has protocol inspection feature and I'm trying to use enecryption to evade that but I always get:

Connected to SERVER:80 (local proxy)

Tunneling to SERVER:443 (destination)
Communication with local proxy:
 -> CONNECT SERVER:443 HTTP/1.0
 -> Proxy-Connection: Keep-Alive
 -> User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)
 <- HTTP/1.0 200 Connection Established
 <- Proxy-agent: Apache/2.4.27 (Ubuntu)


Tunnel established.
error: Socket write error.
ssh_exchange_identification: Connection closed by remote host

Will this work with an SSL MITM Proxy?

I've been able to set this up with a local proxy that does SSL Inspection, but I can't seem to establish an SSH connection with my home machine. The local proxy (run by my organization) effectively performs a man in the middle attack on every HTTPS CONNECT request that it receives, meaning it's able to inspect every packet sent over SSL.

I've set up netcat to listen on my home machine nc -lv -p 443 and then connected to it via proxytunnel on my work machine proxytunnel -v -p work.proxy.com:8080 -r my.proxy.com:443 -d my.homemachine.com:443. With that setup, I've been able to type on my work machine and see the messages on my home machine. So, clearly a tunnel is being established.

If I then attempt to SSH into my home machine using this same command (I have SSH set up on port 443 just in case it helps), ssh -vvv -o "ProxyCommand=proxytunnel -v -p work.proxy.com:8080 -r my.proxy.com:443 -d %h:%p -H 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)'" -p 443 [email protected], I see the initial SSH protocol messages arrive, but then the connection is closed by the local proxy (Output below).

My theory is that the local proxy is inspecting the sent packets, detecting whether the messages resemble an SSH handshake, and closing the connection if they do. That's the only way I can explain being able to establish a tunnel and send arbitrary text over it, while still seeing these SSH connections being closed.

My question being: Can proxytunnel be thwarted by MITM, SSL inspection proxy servers? If so, is there another tool that works around this?

OpenSSH_for_Windows_7.6p1, LibreSSL 2.6.4
debug3: Failed to open file:C:\\Users\\myuser/.ssh/config error:2
debug3: Failed to open file:C:\\ProgramData\\ssh/ssh_config error:2
debug1: Executing proxy command: exec Cproxytunnel.exe -v -p work.proxy.com:8080 -r my.proxy.com:443 -d my.homemachine.com:443 -H 'User-Agent:  Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/11.11.11.11 Safari/537.36'

debug3: spawning proxytunnel.exe -v -p work.proxy.com:8080 -r my.proxy.com:443 -d my.homemachine.com:22 -H 'User-Agent:  Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/11.11.11.11 Safari/537.36'
debug3: w32_getpeername ERROR: not sock :2
debug1: identity file C:\\Users\\myuser/.ssh/id_rsa type 0
[Some messages about identify files - not relevant]
debug1: identity file C:\\Users\\myuser/.ssh/id_ed25519-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_for_Windows_7.6
Local proxy work.proxy.com resolves to 11.11.11.11
Connected to work.proxy.com:8080 (local proxy)

Tunneling to my.proxy.com:443 (remote proxy)
Communication with local proxy:
 -> CONNECT my.proxy.com:443 HTTP/1.0
 -> Proxy-Connection: Keep-Alive
 -> User-Agent:  Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/11.11.11.11 Safari/537.36
 <- HTTP/1.1 200 Connection Established
 <- Proxy-Agent: Zscaler/6.0

Tunneling to my.homemachine.com:443 (destination)
Communication with remote proxy:
 -> CONNECT my.homemachine.com:443 HTTP/1.0
 -> Proxy-Connection: Keep-Alive
 -> User-Agent:  Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/11.11.11.11 Safari/537.36
 <- HTTP/1.1 200 Connection Established
 <- Proxy-Agent: Zscaler/6.0

Tunnel established.
debug1: Remote protocol version 2.0, remote software version OpenSSH_for_Windows_7.7
debug1: match: OpenSSH_for_Windows_7.7 pat OpenSSH* compat 0x04000000
debug2: fd 5 setting O_NONBLOCK
debug2: fd 4 setting O_NONBLOCK
debug1: Authenticating to my.homemachine.com:22 as 'MY-HOMEMACHINE\\myuser'
debug3: hostkeys_foreach: reading file "C:\\Users\\myuser/.ssh/known_hosts"
debug3: Failed to open file:C:\\Users\\myuser/.ssh/known_hosts2 error:2
debug3: Failed to open file:C:\\ProgramData\\ssh/ssh_known_hosts error:2
debug3: Failed to open file:C:\\ProgramData\\ssh/ssh_known_hosts2 error:2
debug3: send packet: type 20
debug1: SSH2_MSG_KEXINIT sent
Tunnel closed.

[Feature request] Clarify the different setup types in the README

The ways proxytunnel can be used is not straightforward IMO, because it greatly depends on the situation you are in. Especially the most powerful option, of encrypting your traffic with HTTPS requires some advanced setup, which is relegated to being discussed in a fairly old blog post.

This project made some excellent info summary with the 2008 Froscon conference entry, as linked by the project homepage. All perserved in well scaling vector graphics, all that achieved 15 years ago, an era in computing I don't remember being good with documentation. I would suggest exporting those illustrations as an SVG and using them in the README, like this SVG exported from from page 16:
Bild2

Lastly, I think the way HTTPS encryption is explained, should clarify some points. First of all: proxytunnel is always supposed to be used by the client, never the remote server. (Unless I misunderstood it...) Initially when reading the doc, I thought proxytunnel sits at both ends if encryption is required. Only once I read the slides, did it finally click and I started using proxytunnel successfully.
Also, it appears that for HTTPS Encryption to work, a 2nd hop / 2hop setup is always required. I don't think that's the case. Usually it is possible to contact a website on :443 without requiring the specification of the "first hop" proxy. If you only want to connect to a remote SSH server,the only thing required is that server accepting HTTP CONNECT, connecting to localhost 22 and encrypting the resulting traffic. Such a setup is single-hop, not 2hop and would go through a corporate firewall, depending on the setup and where that firewall is applied.

If you agree those suggestions to be sensible, I could also make a README PR myself.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.