zweibaranov
zweibaranov

Reputation: 570

Make Emacs access to HTTPS over Socks proxy

This issue drove me crazy. I have a local SOCKSv5 proxy which is a gateway for all application on the system. I'd like to make url-retrieve-synchronously go though the SOCKS. With the following settings:

(setq socks-noproxy '("127.0.0.1"))
(setq socks-server '("Default server" "127.0.0.1" 8010 5))
(setq url-gateway-method 'socks)

The retrieve over plain HTTP works ok:

(url-retrieve-synchronously "http://gnu.org")
#<buffer  *http www.gnu.org:80*>

But it does not work for HTTPS:

(url-retrieve-synchronously "https://gnu.org")

It causes:

Debugger entered--Lisp error: (file-error "make client process failed" "connection timed out" :name "gnu.org" :buffer #<buffer  *url-http-temp*> :host "gnu.org" :service 443 :nowait nil)
  make-network-process(:name "gnu.org" :buffer #<buffer  *url-http-temp*> :host    "gnu.org" :service 443 :nowait nil)
  open-network-stream("gnu.org" #<buffer  *url-http-temp*> "gnu.org" 443)
  open-gnutls-stream("gnu.org" #<buffer  *url-http-temp*> "gnu.org" 443)
  network-stream-open-tls("gnu.org" #<buffer  *url-http-temp*> "gnu.org" 443 (:type tls :nowait nil))
  open-network-stream("gnu.org" #<buffer  *url-http-temp*> "gnu.org" 443 :type tls :nowait nil)
  byte-code("\306\211\n\307>\203$

Question: how to make HTTPS work over socks in Emacs? My version is 24.2.50/W32

I understand that for some reason an original open-network-stream is used instead socks-open-network-stream. I tried to breakpoint url-open-stream using edebug but did not manage to understand why the breakpoint is not triggered. Any ideas?

Thanks.

Upvotes: 5

Views: 6762

Answers (6)

huming.chen
huming.chen

Reputation: 1

My Emacs version is 28.1, I tried the following config, and it worked like a charm, btw, I use v2ray in the background.

(setq url-proxy-services
  '(("no_proxy" . "^.*example.com")
    ("https" . "localhost:1087")
    ("http" . "localhost:1087")
    ;; socks not working, @see url-default-find-proxy-for-url
    ;; ("socks5" . "localhost:1080")
    ))

Upvotes: 0

南山竹
南山竹

Reputation: 524

It's a bug above Emacs 26.3 in url-http function, the signature of url-http look like this:

(defun url-http (url callback cbargs &optional retry-buffer gateway-method) ...)

The optional gateway-method argument try to overwrite url-gateway-method but been wrong coded:

(connection (url-http-find-free-connection 
                (url-host url)
                (url-port url)
                gateway-method))

The right way to do that:

(connection (url-http-find-free-connection 
                 (url-host url)
                 (url-port url)
                 (or gateway-method url-gateway-method)))

In Emacs 24 version, url-gateway-method local variable had hard coded to 'tls

(defmacro url-https-create-secure-wrapper (method args)
  `(defun ,(intern (format (if method "url-https-%s" "url-https") method)) ,args
    ,(format "HTTPS wrapper around `%s' call." (or method "url-http"))
    (let ((url-gateway-method 'tls))
      (,(intern (format (if method "url-http-%s" "url-http") method))
       ,@(remove '&rest (remove '&optional args))))))

The fix for Emacs version >= 25:

(defadvice url-http (around url-http-around activate disable)
        "Fix the `url-gateway-method' bug in `url-http'."
        (if (eq 'socks url-gateway-method)
            (let ((gateway-method url-gateway-method))
              ad-do-it)
          ad-do-it))

The fix for Emacs version < 25:

(defvar *url-gateway-method* nil
  "Alias of `url-gateway-method' used to fix the bug in `url-http'.")

(defadvice url-http (around url-http-around compile)
  "Fix the `url-gateway-method' bug in `url-https'."
  (let ((url-gateway-method (if (eq *url-gateway-method* 'socks)
                                'socks
                              'tls)))
    ad-do-it))

Finally, you can review the fix here: https://github.com/junjiemars/.emacs.d/blob/cc/config/sockets.el.

Upvotes: 1

user3601435
user3601435

Reputation: 467

It fixed in emacs current version (checked 25.2.2)

Upvotes: 0

tangxinfa
tangxinfa

Reputation: 1510

Create ~/.emacs.d/w3m.sh:

#!/bin/bash

proxychains /usr/bin/w3m "$@"

Custom w3m:

(setq w3m-command "~/.emacs.d/w3m.sh")

Then only w3m use proxy.

Upvotes: 0

user4802121
user4802121

Reputation:

GamerH2o - I've never got

proxychains emacs & 

to work. For me, I have to do

proxychains bash-script.sh &

where the bash-script.sh is a script

#!/bin/bash
/path/to/emacs --debug-init --geometry 83X40 --no-splash & ;;
exit 0

which launches emacs. My actual script is a little more complicated than above since I include various options, but that's the general idea. I can now use w3m or eww as "emacs internet-browsers". My passage through the dns servers is echo'd in the xterm. (I'm using tor rather than "free anon servers".)

Upvotes: 1

Zhao Gang
Zhao Gang

Reputation: 33

Another approach is to use program proxychains to start emacs from command line, proxychains supports HTTP socks4 and socks5 proxy protocols. The code may be:

proxychains emacs &

Needless to say you have to configure your proxy setting in proxychains instead of in emacs.

PS: Don't forget to set proxychains in quiet_mode in its configure file(/etc/proxychains.conf), or the verbose output may annony you. It's not the default set at least on Fedora.

Upvotes: 1

Related Questions