Skip to content

Commit

Permalink
Merge pull request #51 from Snawoot/cafile
Browse files Browse the repository at this point in the history
add cafile option
  • Loading branch information
Snawoot authored Jul 17, 2021
2 parents 27381ce + 26990c6 commit 458efb3
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ zagent248.hola.org,165.22.65.3,22222,22223,22224,22225,22226,digitalocean
| Argument | Type | Description |
| -------- | ---- | ----------- |
| bind-address | String | HTTP proxy address to listen to (default "127.0.0.1:8080") |
| cafile | String | use custom CA certificate bundle file |
| country | String | desired proxy location (default "us") |
| dont-use-trial | - | use regular ports instead of trial ports |
| force-port-field | Number | force specific port field/num (example 24232 or lum) |
Expand Down
15 changes: 14 additions & 1 deletion holaapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package main
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/json"
Expand Down Expand Up @@ -333,10 +335,16 @@ var baseDialer ContextDialer = &net.Dialer{
KeepAlive: 30 * time.Second,
}

var tlsConfig *tls.Config

func UpdateHolaDialer(dialer ContextDialer) {
baseDialer = dialer
}

func UpdateHolaTLSConfig(config *tls.Config) {
tlsConfig = config
}

// Returns default http client with a proxy override
func httpClientWithProxy(agent *FallbackAgent) *http.Client {
t := &http.Transport{
Expand All @@ -345,10 +353,15 @@ func httpClientWithProxy(agent *FallbackAgent) *http.Client {
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: tlsConfig,
}
var dialer ContextDialer = baseDialer
var rootCAs *x509.CertPool
if tlsConfig != nil {
rootCAs = tlsConfig.RootCAs
}
if agent != nil {
dialer = NewProxyDialer(agent.NetAddr(), agent.Hostname(), nil, dialer)
dialer = NewProxyDialer(agent.NetAddr(), agent.Hostname(), rootCAs, nil, dialer)
}
t.DialContext = dialer.DialContext
return &http.Client{
Expand Down
45 changes: 34 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package main

import (
"crypto/tls"
"crypto/x509"
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
Expand Down Expand Up @@ -50,6 +53,7 @@ type CLIArgs struct {
force_port_field string
showVersion bool
proxy string
caFile string
}

func parse_args() CLIArgs {
Expand All @@ -74,6 +78,7 @@ func parse_args() CLIArgs {
flag.StringVar(&args.proxy, "proxy", "", "sets base proxy to use for all dial-outs. "+
"Format: <http|https|socks5|socks5h>://[login:password@]host[:port] "+
"Examples: http://user:password@192.168.1.1:3128, socks5://10.0.0.1:1080")
flag.StringVar(&args.caFile, "cafile", "", "use custom CA certificate bundle file")
flag.Parse()
if args.country == "" {
arg_fail("Country can't be empty string.")
Expand All @@ -87,15 +92,6 @@ func parse_args() CLIArgs {
return args
}

func proxyFromURLWrapper(u *url.URL, next xproxy.Dialer) (xproxy.Dialer, error) {
cdialer, ok := next.(ContextDialer)
if !ok {
return nil, errors.New("only context dialers are accepted")
}

return ProxyDialerFromURL(u, cdialer)
}

func run() int {
args := parse_args()
if args.showVersion {
Expand All @@ -120,6 +116,33 @@ func run() int {
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}

var caPool *x509.CertPool
if args.caFile != "" {
caPool = x509.NewCertPool()
certs, err := ioutil.ReadFile(args.caFile)
if err != nil {
mainLogger.Error("Can't load CA file: %v", err)
return 15
}
if ok := caPool.AppendCertsFromPEM(certs); !ok {
mainLogger.Error("Can't load certificates from CA file")
return 15
}
UpdateHolaTLSConfig(&tls.Config{
RootCAs: caPool,
})
}

proxyFromURLWrapper := func(u *url.URL, next xproxy.Dialer) (xproxy.Dialer, error) {
cdialer, ok := next.(ContextDialer)
if !ok {
return nil, errors.New("only context dialers are accepted")
}

return ProxyDialerFromURL(u, caPool, cdialer)
}

if args.proxy != "" {
xproxy.RegisterDialerType("http", proxyFromURLWrapper)
xproxy.RegisterDialerType("https", proxyFromURLWrapper)
Expand Down Expand Up @@ -163,8 +186,8 @@ func run() int {
mainLogger.Critical("Unable to determine proxy endpoint: %v", err)
return 5
}
handlerDialer := NewProxyDialer(endpoint.NetAddr(), endpoint.TLSName, auth, dialer)
requestDialer := NewPlaintextDialer(endpoint.NetAddr(), endpoint.TLSName, dialer)
handlerDialer := NewProxyDialer(endpoint.NetAddr(), endpoint.TLSName, caPool, auth, dialer)
requestDialer := NewPlaintextDialer(endpoint.NetAddr(), endpoint.TLSName, caPool, dialer)
mainLogger.Info("Endpoint: %s", endpoint.URL().String())
mainLogger.Info("Starting proxy server...")
handler := NewProxyHandler(handlerDialer, requestDialer, auth, resolver, proxyLogger)
Expand Down
5 changes: 4 additions & 1 deletion plaintext.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ type PlaintextDialer struct {
fixedAddress string
tlsServerName string
next ContextDialer
caPool *x509.CertPool
}

func NewPlaintextDialer(address, tlsServerName string, next ContextDialer) *PlaintextDialer {
func NewPlaintextDialer(address, tlsServerName string, caPool *x509.CertPool, next ContextDialer) *PlaintextDialer {
return &PlaintextDialer{
fixedAddress: address,
tlsServerName: tlsServerName,
next: next,
caPool: caPool,
}
}

Expand All @@ -45,6 +47,7 @@ func (d *PlaintextDialer) DialContext(ctx context.Context, network, address stri
opts := x509.VerifyOptions{
DNSName: d.tlsServerName,
Intermediates: x509.NewCertPool(),
Roots: d.caPool,
}
for _, cert := range cs.PeerCertificates[1:] {
opts.Intermediates.AddCert(cert)
Expand Down
9 changes: 6 additions & 3 deletions upstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,20 @@ type ProxyDialer struct {
tlsServerName string
auth AuthProvider
next ContextDialer
caPool *x509.CertPool
}

func NewProxyDialer(address, tlsServerName string, auth AuthProvider, nextDialer ContextDialer) *ProxyDialer {
func NewProxyDialer(address, tlsServerName string, caPool *x509.CertPool, auth AuthProvider, nextDialer ContextDialer) *ProxyDialer {
return &ProxyDialer{
address: address,
tlsServerName: tlsServerName,
auth: auth,
next: nextDialer,
caPool: caPool,
}
}

func ProxyDialerFromURL(u *url.URL, next ContextDialer) (*ProxyDialer, error) {
func ProxyDialerFromURL(u *url.URL, caPool *x509.CertPool, next ContextDialer) (*ProxyDialer, error) {
host := u.Hostname()
port := u.Port()
tlsServerName := ""
Expand Down Expand Up @@ -79,7 +81,7 @@ func ProxyDialerFromURL(u *url.URL, next ContextDialer) (*ProxyDialer, error) {
return authHeader
}
}
return NewProxyDialer(address, tlsServerName, auth, next), nil
return NewProxyDialer(address, tlsServerName, caPool, auth, next), nil
}

func (d *ProxyDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
Expand All @@ -105,6 +107,7 @@ func (d *ProxyDialer) DialContext(ctx context.Context, network, address string)
opts := x509.VerifyOptions{
DNSName: d.tlsServerName,
Intermediates: x509.NewCertPool(),
Roots: d.caPool,
}
for _, cert := range cs.PeerCertificates[1:] {
opts.Intermediates.AddCert(cert)
Expand Down

0 comments on commit 458efb3

Please sign in to comment.