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

Making SOCKS5 proxies with User Authentication work with Chrome #305

Closed
Bolado opened this issue Dec 9, 2020 · 5 comments
Closed

Making SOCKS5 proxies with User Authentication work with Chrome #305

Bolado opened this issue Dec 9, 2020 · 5 comments
Labels
discuss Need review and discussion question Questions related to rod

Comments

@Bolado
Copy link

Bolado commented Dec 9, 2020

Rod Version: v0.84.3

The code to demonstrate your question

httpClient := http.Client{}
var proxyStr string
var auth string
var dialer proxy.Dialer
if len(proxySorted) > 2 {
	auth := proxy.Auth{
		User:     proxySorted[2],
		Password: proxySorted[3],
	}
	dialer, _ = proxy.SOCKS5("tcp", proxySorted[0]+":"+proxySorted[1], &auth, proxy.Direct)
} else {
	dialer, _ = proxy.SOCKS5("tcp", proxySorted[0]+":"+proxySorted[1], nil, proxy.Direct)
}

  transport := &http.Transport{
  Dial: dialer.Dial,
}

httpClient.Transport = transport

While we can just use the above code to set auth for SOCKS proxies on the http.Client{}, we don't have a direct solution for doing that on Chrome, being able to use only SOCKS without user authentication with ease, I have been searching for a solution to be able to create a middleware type of proxy server, that way it would serve, and when I connected to the port, it connects to the remote SOCKS5 proxy and solves the auth for me, but no luck so far to find a solution, goproxy seems to only support HTTP/S type of proxies. Got the idea by a yad comment on a similar issue ( #62 ).

Thanks for your attention!

@Bolado Bolado added the question Questions related to rod label Dec 9, 2020
@ysmood ysmood added the discuss Need review and discussion label Dec 10, 2020
@Bolado
Copy link
Author

Bolado commented Dec 11, 2020

I was able to do it, was at my face the whole time, I thought goproxy only supported HTTP proxies, but no... here is the code block I used:

func createProxyMiddleman(protocol string, remoteProxy []string) (port int, err error) {
	switch protocol {
	case "http":
		portProxy, _ := freeport.GetFreePort()
		middleProxy := goproxy.NewProxyHttpServer()
		middleProxy.Tr.Proxy = func(req *http.Request) (*url.URL, error) {
			return url.Parse("http://" + remoteProxy[0] + ":" + remoteProxy[1])
		}
		middleProxy.Logger = httpLogger()
		connectReqHandler := func(req *http.Request) {
			SetBasicAuth(remoteProxy[2], remoteProxy[3], req)
		}
		middleProxy.ConnectDial = middleProxy.NewConnectDialToProxyWithHandler("http://"+remoteProxy[0]+":"+remoteProxy[1], connectReqHandler)

		middleProxy.OnRequest().Do(goproxy.FuncReqHandler(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			SetBasicAuth(username, password, req)
			return req, nil
		}))
		go http.ListenAndServe("localhost:"+strconv.Itoa(portProxy), middleProxy)
		return portProxy, nil
	case "socks":

		var dialer proxy.Dialer

		auth := proxy.Auth{
			User:     remoteProxy[2],
			Password: remoteProxy[3],
		}
		dialer, _ = proxy.SOCKS5("tcp", remoteProxy[0]+":"+remoteProxy[1], &auth, proxy.Direct)

		transport := &http.Transport{
			Dial: dialer.Dial,
		}
		portProxy, _ := freeport.GetFreePort()
		middleProxy := goproxy.NewProxyHttpServer()
		middleProxy.Tr = transport
		middleProxy.Logger = httpLogger()
		connectReqHandler := func(req *http.Request) {
			SetBasicAuth(remoteProxy[2], remoteProxy[3], req)
		}
		middleProxy.ConnectDial = middleProxy.NewConnectDialToProxyWithHandler("socks://"+remoteProxy[0]+":"+remoteProxy[1], connectReqHandler)

		middleProxy.OnRequest().Do(goproxy.FuncReqHandler(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			SetBasicAuth(username, password, req)
			return req, nil
		}))

		go http.ListenAndServe("localhost:"+strconv.Itoa(portProxy), middleProxy)
		return portProxy, nil
	}
	return 0, fmt.Errorf("proxy type invalid")
}

Hope it helps somebody ☺
And thanks yad for everything you do with rod !

@Bolado Bolado closed this as completed Dec 11, 2020
@ysmood
Copy link
Member

ysmood commented Dec 12, 2020

Nice job 👍

@allanpk716
Copy link

need change

middleProxy.ConnectDial = middleProxy.NewConnectDialToProxyWithHandler("socks://"+remoteProxy[0]+":"+remoteProxy[1], connectReqHandler)

to

dialContextOld := func(network, address string) (net.Conn, error) { return dialer.Dial(network, address) } middleProxy.ConnectDial = dialContextOld

because NewConnectDialToProxyWithHandler not support socks:// protocol

@ysmood ysmood mentioned this issue Aug 30, 2022
@cplasfwst
Copy link

我能够做到这一点,一直在我面前,我以为 goproxy 只支持 HTTP 代理,但不......这是我使用的代码块:

func createProxyMiddleman(protocol string, remoteProxy []string) (port int, err error) {
	switch protocol {
	case "http":
		portProxy, _ := freeport.GetFreePort()
		middleProxy := goproxy.NewProxyHttpServer()
		middleProxy.Tr.Proxy = func(req *http.Request) (*url.URL, error) {
			return url.Parse("http://" + remoteProxy[0] + ":" + remoteProxy[1])
		}
		middleProxy.Logger = httpLogger()
		connectReqHandler := func(req *http.Request) {
			SetBasicAuth(remoteProxy[2], remoteProxy[3], req)
		}
		middleProxy.ConnectDial = middleProxy.NewConnectDialToProxyWithHandler("http://"+remoteProxy[0]+":"+remoteProxy[1], connectReqHandler)

		middleProxy.OnRequest().Do(goproxy.FuncReqHandler(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			SetBasicAuth(username, password, req)
			return req, nil
		}))
		go http.ListenAndServe("localhost:"+strconv.Itoa(portProxy), middleProxy)
		return portProxy, nil
	case "socks":

		var dialer proxy.Dialer

		auth := proxy.Auth{
			User:     remoteProxy[2],
			Password: remoteProxy[3],
		}
		dialer, _ = proxy.SOCKS5("tcp", remoteProxy[0]+":"+remoteProxy[1], &auth, proxy.Direct)

		transport := &http.Transport{
			Dial: dialer.Dial,
		}
		portProxy, _ := freeport.GetFreePort()
		middleProxy := goproxy.NewProxyHttpServer()
		middleProxy.Tr = transport
		middleProxy.Logger = httpLogger()
		connectReqHandler := func(req *http.Request) {
			SetBasicAuth(remoteProxy[2], remoteProxy[3], req)
		}
		middleProxy.ConnectDial = middleProxy.NewConnectDialToProxyWithHandler("socks://"+remoteProxy[0]+":"+remoteProxy[1], connectReqHandler)

		middleProxy.OnRequest().Do(goproxy.FuncReqHandler(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			SetBasicAuth(username, password, req)
			return req, nil
		}))

		go http.ListenAndServe("localhost:"+strconv.Itoa(portProxy), middleProxy)
		return portProxy, nil
	}
	return 0, fmt.Errorf("proxy type invalid")
}

希望它对某人有帮助 ☺ 感谢您使用 rod 所做的一切!

Can I ask for a complete example? I don't understand, or what packages need to be imported?

@cplasfwst
Copy link

需要改变

middleProxy.ConnectDial = middleProxy.NewConnectDialToProxyWithHandler("socks://"+remoteProxy[0]+":"+remoteProxy[1], connectReqHandler)

dialContextOld := func(network, address string) (net.Conn, error) { return dialer.Dial(network, address) } middleProxy.ConnectDial = dialContextOld

因为NewConnectDialToProxyWithHandler不支持socks://协议

Could you please guide me as to which third-party library is goproxy in this method? or URL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discuss Need review and discussion question Questions related to rod
Projects
None yet
Development

No branches or pull requests

4 participants