From 866e8dac8a694503f3f7a51671ad87c8d769f55f Mon Sep 17 00:00:00 2001 From: Brenton Morris Date: Mon, 14 Sep 2015 16:32:23 +1200 Subject: [PATCH 1/2] Added proxy support --- client/connection.go | 47 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/client/connection.go b/client/connection.go index 903f7c6..732c3a8 100644 --- a/client/connection.go +++ b/client/connection.go @@ -11,6 +11,8 @@ import ( "strings" "sync" "time" + "golang.org/x/net/proxy" + "net/url" ) // Conn encapsulates a connection to a single IRC server. Create @@ -33,6 +35,7 @@ type Conn struct { // I/O stuff to server dialer *net.Dialer + proxyDialer proxy.Dialer sock net.Conn io *bufio.ReadWriter in chan *Line @@ -70,6 +73,13 @@ type Config struct { SSL bool SSLConfig *tls.Config + // Are we connecting via proxy? Set this to true to connect via + // the proxy server provided. + // Changing these after connection will have no effect until the + // client reconnects. + Proxy bool + ProxyServer string + // Local address to bind to when connecting to the server. LocalAddr string @@ -279,6 +289,9 @@ func (conn *Conn) ConnectTo(host string, pass ...string) error { // To enable explicit SSL on the connection to the IRC server, set Config.SSL // to true before calling Connect(). The port will default to 6697 if SSL is // enabled, and 6667 otherwise. +// To enable connecting via a proxy server, set Config.Proxy to true and +// Config.ProxyServer to the proxy URL (example socks5://localhost:9000) before +// before calling Connect(). // // Upon successful connection, Connected will return true and a REGISTER event // will be fired. This is mostly for internal use; it is suggested that a @@ -295,27 +308,45 @@ func (conn *Conn) Connect() error { if conn.connected { return fmt.Errorf("irc.Connect(): Cannot connect to %s, already connected.", conn.cfg.Server) } - if conn.cfg.SSL { - if !hasPort(conn.cfg.Server) { + + if !hasPort(conn.cfg.Server) { + if conn.cfg.SSL { conn.cfg.Server = net.JoinHostPort(conn.cfg.Server, "6697") + } else { + conn.cfg.Server = net.JoinHostPort(conn.cfg.Server, "6667") } - logging.Info("irc.Connect(): Connecting to %s with SSL.", conn.cfg.Server) - if s, err := tls.DialWithDialer(conn.dialer, "tcp", conn.cfg.Server, conn.cfg.SSLConfig); err == nil { + } + + if conn.cfg.Proxy { + proxyURL, err := url.Parse(conn.cfg.ProxyServer) + if err != nil { + return err + } + conn.proxyDialer, err = proxy.FromURL(proxyURL, conn.dialer) + if err != nil { + return err + } + + logging.Info("irc.Connect(): Connecting to %s.", conn.cfg.Server) + if s, err := conn.proxyDialer.Dial("tcp", conn.cfg.Server); err == nil { conn.sock = s } else { return err } } else { - if !hasPort(conn.cfg.Server) { - conn.cfg.Server = net.JoinHostPort(conn.cfg.Server, "6667") - } - logging.Info("irc.Connect(): Connecting to %s without SSL.", conn.cfg.Server) + logging.Info("irc.Connect(): Connecting to %s.", conn.cfg.Server) if s, err := conn.dialer.Dial("tcp", conn.cfg.Server); err == nil { conn.sock = s } else { return err } } + + if conn.cfg.SSL { + logging.Info("irc.Connect(): Performing SSL handshake.") + conn.sock = tls.Client(conn.sock, conn.cfg.SSLConfig) + } + conn.postConnect(true) conn.connected = true conn.dispatch(&Line{Cmd: REGISTER, Time: time.Now()}) From f90b498ac4332b1d36322e425334fe6ae3527be9 Mon Sep 17 00:00:00 2001 From: Brenton Morris Date: Sun, 20 Sep 2015 19:37:26 +1200 Subject: [PATCH 2/2] Removed the config.Proxy variable and renamed config.ProxyServer to config.Proxy. Client now connects over the specified proxy if config.Proxy isn't an empty string. --- client/connection.go | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/client/connection.go b/client/connection.go index 732c3a8..e46b50d 100644 --- a/client/connection.go +++ b/client/connection.go @@ -4,15 +4,16 @@ import ( "bufio" "crypto/tls" "fmt" - "github.com/fluffle/goirc/logging" - "github.com/fluffle/goirc/state" "io" "net" + "net/url" "strings" "sync" "time" + + "github.com/fluffle/goirc/logging" + "github.com/fluffle/goirc/state" "golang.org/x/net/proxy" - "net/url" ) // Conn encapsulates a connection to a single IRC server. Create @@ -34,13 +35,13 @@ type Conn struct { stRemovers []Remover // I/O stuff to server - dialer *net.Dialer + dialer *net.Dialer proxyDialer proxy.Dialer - sock net.Conn - io *bufio.ReadWriter - in chan *Line - out chan string - connected bool + sock net.Conn + io *bufio.ReadWriter + in chan *Line + out chan string + connected bool // Control channel and WaitGroup for goroutines die chan struct{} @@ -73,12 +74,10 @@ type Config struct { SSL bool SSLConfig *tls.Config - // Are we connecting via proxy? Set this to true to connect via - // the proxy server provided. + // To connect via proxy set the proxy url here. // Changing these after connection will have no effect until the // client reconnects. - Proxy bool - ProxyServer string + Proxy string // Local address to bind to when connecting to the server. LocalAddr string @@ -111,7 +110,6 @@ type Config struct { // Split PRIVMSGs, NOTICEs and CTCPs longer than SplitLen characters // over multiple lines. Default to 450 if not set. SplitLen int - } // NewConfig creates a Config struct containing sensible defaults. @@ -289,9 +287,8 @@ func (conn *Conn) ConnectTo(host string, pass ...string) error { // To enable explicit SSL on the connection to the IRC server, set Config.SSL // to true before calling Connect(). The port will default to 6697 if SSL is // enabled, and 6667 otherwise. -// To enable connecting via a proxy server, set Config.Proxy to true and -// Config.ProxyServer to the proxy URL (example socks5://localhost:9000) before -// before calling Connect(). +// To enable connecting via a proxy server, set Config.Proxy to the proxy URL +// (example socks5://localhost:9000) before calling Connect(). // // Upon successful connection, Connected will return true and a REGISTER event // will be fired. This is mostly for internal use; it is suggested that a @@ -317,8 +314,8 @@ func (conn *Conn) Connect() error { } } - if conn.cfg.Proxy { - proxyURL, err := url.Parse(conn.cfg.ProxyServer) + if conn.cfg.Proxy != "" { + proxyURL, err := url.Parse(conn.cfg.Proxy) if err != nil { return err }