proxy: use for updater & SMTP

imports a new package to create a HTTP proxy dialer for the SMTP client.
This commit is contained in:
Harvey Tindall 2023-10-05 12:32:25 +01:00
parent 523902f951
commit 5702e8012c
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
9 changed files with 105 additions and 27 deletions

View File

@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"github.com/hrfee/jfa-go/easyproxy"
"gopkg.in/ini.v1"
)
@ -135,6 +136,22 @@ func (app *appContext) loadConfig() error {
messagesEnabled = false
}
if app.proxyEnabled = app.config.Section("advanced").Key("proxy").MustBool(false); app.proxyEnabled {
app.proxyConfig = easyproxy.ProxyConfig{}
app.proxyConfig.Protocol = easyproxy.HTTP
if strings.Contains(app.config.Section("advanced").Key("proxy_protocol").MustString("http"), "socks") {
app.proxyConfig.Protocol = easyproxy.SOCKS5
}
app.proxyConfig.Addr = app.config.Section("advanced").Key("proxy_address").MustString("")
app.proxyConfig.User = app.config.Section("advanced").Key("proxy_user").MustString("")
app.proxyConfig.Password = app.config.Section("advanced").Key("proxy_password").MustString("")
app.proxyTransport, err = easyproxy.NewTransport(app.proxyConfig)
if err != nil {
app.err.Printf("Failed to initialize Proxy: %v\n", err)
}
app.proxyEnabled = true
}
app.MustSetValue("updates", "enabled", "true")
releaseChannel := app.config.Section("updates").Key("channel").String()
if app.config.Section("updates").Key("enabled").MustBool(false) {
@ -147,6 +164,9 @@ func (app *appContext) loadConfig() error {
v = "git"
}
app.updater = newUpdater(baseURL, namespace, repo, v, commit, updater)
if app.proxyEnabled {
app.updater.SetTransport(app.proxyTransport)
}
}
if releaseChannel == "" {
if version == "git" {

View File

@ -1,10 +1,12 @@
// Package easyproxy provides a method to quickly create a http.Transport using given proxy details (SOCKS5 or HTTP).
// Package easyproxy provides a method to quickly create a http.Transport or net.Conn using given proxy details (SOCKS5 or HTTP).
package easyproxy
import (
"crypto/tls"
"net/http"
"net/url"
"github.com/magisterquis/connectproxy"
"golang.org/x/net/proxy"
)
@ -15,28 +17,67 @@ const (
HTTP // HTTP
)
type ProxyConfig struct {
Protocol Protocol
Addr string
User string
Password string
}
// NewTransport returns a http.Transport using the given proxy details. Leave user/pass blank if not needed.
func NewTransport(p Protocol, addr, user, pass string) (*http.Transport, error) {
func NewTransport(c ProxyConfig) (*http.Transport, error) {
t := &http.Transport{}
if p == HTTP {
if c.Protocol == HTTP {
u := &url.URL{
Scheme: "http",
Host: addr,
Host: c.Addr,
}
if user != "" && pass != "" {
u.User = url.UserPassword(user, pass)
if c.User != "" && c.Password != "" {
u.User = url.UserPassword(c.User, c.Password)
}
t.Proxy = http.ProxyURL(u)
return t, nil
}
var auth *proxy.Auth = nil
if user != "" && pass != "" {
auth = &proxy.Auth{User: user, Password: pass}
if c.User != "" && c.Password != "" {
auth = &proxy.Auth{User: c.User, Password: c.Password}
}
dialer, err := proxy.SOCKS5("tcp", addr, auth, proxy.Direct)
dialer, err := proxy.SOCKS5("tcp", c.Addr, auth, proxy.Direct)
if err != nil {
return nil, nil
return nil, err
}
t.Dial = dialer.Dial
return t, nil
}
// NewConn returns a tls.Conn to "addr" using the given proxy details. Leave user/pass blank if not needed.
func NewConn(c ProxyConfig, addr string, tlsConf *tls.Config) (*tls.Conn, error) {
var proxyDialer proxy.Dialer
var err error
if c.Protocol == SOCKS5 {
var auth *proxy.Auth = nil
if c.User != "" && c.Password != "" {
auth = &proxy.Auth{User: c.User, Password: c.Password}
}
proxyDialer, err = proxy.SOCKS5("tcp", c.Addr, auth, proxy.Direct)
if err != nil {
return nil, err
}
} else {
u := &url.URL{
Scheme: "http",
Host: c.Addr,
}
if c.User != "" && c.Password != "" {
u.User = url.UserPassword(c.User, c.Password)
}
proxyDialer, err = connectproxy.New(u, proxy.Direct)
}
dialer, err := proxyDialer.Dial("tcp", addr)
if err != nil {
return nil, err
}
conn := tls.Client(dialer, tlsConf)
return conn, nil
}

View File

@ -3,3 +3,5 @@ module github.com/hrfee/jfa-go/easyproxy
go 1.20
require golang.org/x/net v0.15.0
require github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b // indirect

View File

@ -1,2 +1,4 @@
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=

View File

@ -19,6 +19,7 @@ import (
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/hrfee/jfa-go/easyproxy"
"github.com/hrfee/mediabrowser"
"github.com/itchyny/timefmt-go"
"github.com/mailgun/mailgun-go/v4"
@ -87,7 +88,11 @@ func NewEmailer(app *appContext) *Emailer {
if username == "" && password != "" {
username = emailer.fromAddr
}
err := emailer.NewSMTP(app.config.Section("smtp").Key("server").String(), app.config.Section("smtp").Key("port").MustInt(465), username, password, sslTLS, app.config.Section("smtp").Key("ssl_cert").MustString(""), app.config.Section("smtp").Key("hello_hostname").String(), app.config.Section("smtp").Key("cert_validation").MustBool(true))
var proxyConf *easyproxy.ProxyConfig = nil
if app.proxyEnabled {
proxyConf = &app.proxyConfig
}
err := emailer.NewSMTP(app.config.Section("smtp").Key("server").String(), app.config.Section("smtp").Key("port").MustInt(465), username, password, sslTLS, app.config.Section("smtp").Key("ssl_cert").MustString(""), app.config.Section("smtp").Key("hello_hostname").String(), app.config.Section("smtp").Key("cert_validation").MustBool(true), proxyConf)
if err != nil {
app.err.Printf("Error while initiating SMTP mailer: %v", err)
}
@ -113,7 +118,7 @@ type SMTP struct {
}
// NewSMTP returns an SMTP emailClient.
func (emailer *Emailer) NewSMTP(server string, port int, username, password string, sslTLS bool, certPath string, helloHostname string, validateCertificate bool) (err error) {
func (emailer *Emailer) NewSMTP(server string, port int, username, password string, sslTLS bool, certPath string, helloHostname string, validateCertificate bool, proxy *easyproxy.ProxyConfig) (err error) {
sender := &SMTP{}
sender.Client = sMail.NewSMTPClient()
if sslTLS {
@ -131,12 +136,16 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
sender.Client.Host = server
sender.Client.Port = port
sender.Client.KeepAlive = false
// x509.SystemCertPool is unavailable on windows
if PLATFORM == "windows" {
sender.Client.TLSConfig = &tls.Config{
InsecureSkipVerify: !validateCertificate,
ServerName: server,
}
if proxy != nil {
sender.Client.CustomConn, err = easyproxy.NewConn(*proxy, fmt.Sprintf("%s:%d", server, port), sender.Client.TLSConfig)
}
emailer.sender = sender
return
}
@ -156,6 +165,9 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
ServerName: server,
RootCAs: rootCAs,
}
if proxy != nil {
sender.Client.CustomConn, err = easyproxy.NewConn(*proxy, fmt.Sprintf("%s:%d", server, port), sender.Client.TLSConfig)
}
emailer.sender = sender
return
}

3
go.mod
View File

@ -43,7 +43,7 @@ require (
github.com/swaggo/gin-swagger v1.6.0
github.com/timshannon/badgerhold/v4 v4.0.2
github.com/writeas/go-strip-markdown v2.0.1+incompatible
github.com/xhit/go-simple-mail/v2 v2.13.0
github.com/xhit/go-simple-mail/v2 v2.16.0
gopkg.in/ini.v1 v1.67.0
maunium.net/go/mautrix v0.15.3
)
@ -93,6 +93,7 @@ require (
github.com/klauspost/compress v1.16.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect

4
go.sum
View File

@ -264,6 +264,8 @@ github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaK
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
github.com/mailgun/mailgun-go/v4 v4.9.1 h1:D/jhJXYod4RqRsNOOSrjrtAcMEnz8mPYJmeA5cueHKY=
github.com/mailgun/mailgun-go/v4 v4.9.1/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@ -394,6 +396,8 @@ github.com/writeas/go-strip-markdown v2.0.1+incompatible h1:IIqxTM5Jr7RzhigcL6Fk
github.com/writeas/go-strip-markdown v2.0.1+incompatible/go.mod h1:Rsyu10ZhbEK9pXdk8V6MVnZmTzRG0alMNLMwa0J01fE=
github.com/xhit/go-simple-mail/v2 v2.13.0 h1:OANWU9jHZrVfBkNkvLf8Ww0fexwpQVF/v/5f96fFTLI=
github.com/xhit/go-simple-mail/v2 v2.13.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
github.com/xhit/go-simple-mail/v2 v2.16.0 h1:ouGy/Ww4kuaqu2E2UrDw7SvLaziWTB60ICLkIkNVccA=
github.com/xhit/go-simple-mail/v2 v2.16.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

19
main.go
View File

@ -114,6 +114,9 @@ type appContext struct {
newUpdate bool // Whether whatever's in update is new.
tag Tag
update Update
proxyEnabled bool
proxyTransport *http.Transport
proxyConfig easyproxy.ProxyConfig
internalPWRs map[string]InternalPWR
ConfirmationKeys map[string]map[string]newUserDTO // Map of invite code to jwt to request
confirmationKeysLock sync.Mutex
@ -392,20 +395,8 @@ func start(asDaemon, firstCall bool) {
app.jf.Verbose = true
}
if app.config.Section("advanced").Key("proxy").MustBool(false) {
// FIXME: Use Proxy
protocol := easyproxy.HTTP
if strings.Contains(app.config.Section("advanced").Key("proxy_protocol").MustString("http"), "socks") {
protocol = easyproxy.SOCKS5
}
addr := app.config.Section("advanced").Key("proxy_address").MustString("")
user := app.config.Section("advanced").Key("proxy_user").MustString("")
password := app.config.Section("advanced").Key("proxy_password").MustString("")
transport, err := easyproxy.NewTransport(protocol, addr, user, password)
if err != nil {
app.err.Printf("Failed to initialize Proxy: %v\n", err)
}
app.jf.SetTransport(transport)
if app.proxyEnabled {
app.jf.SetTransport(app.proxyTransport)
}
var status int

View File

@ -185,6 +185,11 @@ type BuildDTO struct {
Tags map[string]Tag
}
// SetTransport sets the http.Transport to use for requests. Can be used to set a proxy.
func (ud *Updater) SetTransport(t *http.Transport) {
ud.httpClient.Transport = t
}
func (ud *Updater) GetTag() (Tag, int, error) {
if ud.buildType == off {
return Tag{}, -1, nil