From 279093536b5f8039d28e7cf63a455c5d5e9be99e Mon Sep 17 00:00:00 2001 From: "yakumo.izuru" Date: Thu, 20 Apr 2023 06:12:13 +0000 Subject: [PATCH] Incorporate most of the open pull requests found on GitHub Signed-off-by: Izuru Yakumo git-svn-id: file:///srv/svn/repo/yukari/trunk@140 f3bd38d9-da89-464d-a02a-eb04e43141b5 --- README.md | 8 ++++++- config/config.go | 14 +++++++++++ go.mod | 6 ++--- go.sum | 61 ++++++++++++++++++++++++++++++------------------ morty.go | 53 +++++++++++++++++++++++++++++------------ 5 files changed, 100 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 0e6667b..6b047fc 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Features: Requirement: Go version 1.10 or higher. ``` -$ go get github.com/asciimoo/morty +$ go install github.com/asciimoo/morty@latest $ "$GOPATH/bin/morty" --help ``` @@ -37,6 +37,8 @@ $ "$GOPATH/bin/morty" --help Debug mode (default true) -followredirect Follow HTTP GET redirect + -hashparam string + User-defined requesting string HASH parameter name (ie: '/?hash=...' or '/?h=...') (default "mortyhash") -ipv6 Allow IPv6 HTTP requests (default true) -key string @@ -51,6 +53,8 @@ $ "$GOPATH/bin/morty" --help Use a SOCKS5 proxy (ie: 'hostname:port'). Overrides -ipv6. -timeout uint Request timeout (default 5) + -urlparam string + User-defined requesting string URL parameter name (ie: '/?url=...' or '/?u=...') (default "mortyurl") -version Show version ``` @@ -60,6 +64,8 @@ $ "$GOPATH/bin/morty" --help Morty can additionally be configured using the following environment variables: - `MORTY_ADDRESS`: Listen address (default to `127.0.0.1:3000`) - `MORTY_KEY`: HMAC url validation key (base64 encoded) to prevent direct URL opening. Leave blank to disable validation. Use `openssl rand -base64 33` to generate. +- `MORTY_URL_PARAM`: User-defined requesting string URL parameter name (ie: `/?url=...` or `/?u=...`) (default `mortyurl`) +- `MORTY_HASH_PARAM`: User-defined requesting string HASH parameter name (ie: `/?hash=...` or `/?h=...`) (default `mortyhash`) - `DEBUG`: Enable/disable proxy and redirection logs (default to `true`). Set to `false` to disable. ### Docker diff --git a/config/config.go b/config/config.go index 7e528dc..de547a1 100644 --- a/config/config.go +++ b/config/config.go @@ -11,6 +11,9 @@ type Config struct { IPV6 bool RequestTimeout uint FollowRedirect bool + MaxConnsPerHost uint + UrlParameter string + HashParameter string } var DefaultConfig *Config @@ -20,6 +23,14 @@ func init() { if default_listen_addr == "" { default_listen_addr = "127.0.0.1:3000" } + default_url_parameter := os.Getenv("MORTY_URL_PARAM") + if default_url_parameter == "" { + default_url_parameter = "mortyurl" + } + default_hash_parameter := os.Getenv("MORTY_HASH_PARAM") + if default_hash_parameter == "" { + default_hash_parameter = "mortyhash" + } default_key := os.Getenv("MORTY_KEY") DefaultConfig = &Config{ Debug: os.Getenv("DEBUG") != "false", @@ -28,5 +39,8 @@ func init() { IPV6: true, RequestTimeout: 5, FollowRedirect: false, + MaxConnsPerHost: 4, + UrlParameter: default_url_parameter, + HashParameter: default_hash_parameter, } } diff --git a/go.mod b/go.mod index e4836e6..149503d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/asciimoo/morty go 1.14 require ( - github.com/valyala/fasthttp v1.21.0 - golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 - golang.org/x/text v0.3.3 + github.com/valyala/fasthttp v1.34.0 + golang.org/x/net v0.7.0 + golang.org/x/text v0.7.0 ) diff --git a/go.sum b/go.sum index 5878f98..3adf642 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,45 @@ -github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= -github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc= -github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg= -github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.14.0 h1:67bfuW9azCMwW/Jlq/C+VeihNpAuJMWkYPBig1gdi3A= -github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE= -github.com/valyala/fasthttp v1.21.0 h1:fJjaQ7cXdaSF9vDBujlHLDGj7AgoMTMIXvICeePzYbU= -github.com/valyala/fasthttp v1.21.0/go.mod h1:jjraHZVbKOXftJfsOYoAjaeygpj5hr8ermTRJNroD7A= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= +github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 h1:5kGOVHlq0euqwzgTC9Vu15p6fV1Wi0ArVi8da2urnVg= -golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/morty.go b/morty.go index bce9773..723f1d6 100644 --- a/morty.go +++ b/morty.go @@ -65,6 +65,7 @@ var ALLOWED_CONTENTTYPE_FILTER contenttype.Filter = contenttype.NewFilterOr([]co contenttype.NewFilterEquals("image", "bmp", ""), contenttype.NewFilterEquals("image", "x-ms-bmp", ""), contenttype.NewFilterEquals("image", "x-icon", ""), + contenttype.NewFilterEquals("image", "svg", "xml"), // fonts contenttype.NewFilterEquals("application", "font-otf", ""), contenttype.NewFilterEquals("application", "font-ttf", ""), @@ -195,15 +196,22 @@ type RequestConfig struct { type HTMLBodyExtParam struct { BaseURL string HasMortyKey bool + URLParamName string } type HTMLFormExtParam struct { BaseURL string MortyHash string + URLParamName string + HashParamName string +} +type HTMLMainPageFormParam struct { + URLParamName string } var HTML_FORM_EXTENSION *template.Template var HTML_BODY_EXTENSION *template.Template +var HTML_MAIN_PAGE_FORM *template.Template var HTML_HEAD_CONTENT_TYPE string = ` @@ -260,7 +268,7 @@ func init() {
Morty Proxy - + This is a proxified and sanitized view of the page, visit original site.
@@ -280,6 +288,14 @@ input[type=checkbox]#mortytoggle:checked ~ div { display: none; visibility: hidd if err != nil { panic(err) } + HTML_MAIN_PAGE_FORM, err = template.New("html_main_page_form").Parse(` +
+ Visit url: + +
`) + if err != nil { + panic(err) + } } func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) { @@ -288,9 +304,9 @@ func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) { return } - requestHash := popRequestParam(ctx, []byte("mortyhash")) + requestHash := popRequestParam(ctx, []byte(cfg.HashParameter)) - requestURI := popRequestParam(ctx, []byte("mortyurl")) + requestURI := popRequestParam(ctx, []byte(cfg.UrlParameter)) if requestURI == nil { p.serveMainPage(ctx, 200, nil) @@ -300,7 +316,8 @@ func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) { if p.Key != nil { if !verifyRequestURI(requestURI, requestHash, p.Key) { // HTTP status code 403 : Forbidden - p.serveMainPage(ctx, 403, errors.New(`invalid "mortyhash" parameter`)) + error_message := fmt.Sprintf(`invalid "%s" parameter. hint: Hash URL Parameter`, cfg.HashParameter) + p.serveMainPage(ctx, 403, errors.New(error_message)) return } } @@ -351,7 +368,7 @@ func (p *Proxy) ProcessUri(ctx *fasthttp.RequestCtx, requestURIStr string, redir } req.SetRequestURI(requestURIStr) - req.Header.SetUserAgentBytes([]byte("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0")) + req.Header.SetUserAgentBytes([]byte("Mozilla/5.0 (Windows NT 1.0; Win64; x64; rv:112.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")) resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) @@ -487,7 +504,7 @@ func (p *Proxy) ProcessUri(ctx *fasthttp.RequestCtx, requestURIStr string, redir rc := &RequestConfig{Key: p.Key, BaseURL: parsedURI} sanitizeHTML(rc, ctx, responseBody) if !rc.BodyInjected { - p := HTMLBodyExtParam{rc.BaseURL.String(), false} + p := HTMLBodyExtParam{rc.BaseURL.String(), false, cfg.UrlParameter} if len(rc.Key) > 0 { p.HasMortyKey = true } @@ -698,7 +715,7 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) { if rc.Key != nil { key = hash(urlStr, rc.Key) } - err := HTML_FORM_EXTENSION.Execute(out, HTMLFormExtParam{urlStr, key}) + err := HTML_FORM_EXTENSION.Execute(out, HTMLFormExtParam{urlStr, key, cfg.UrlParameter, cfg.HashParameter}) if err != nil { if cfg.Debug { fmt.Println("failed to inject body extension", err) @@ -711,7 +728,7 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) { writeEndTag := true switch string(tag) { case "body": - p := HTMLBodyExtParam{rc.BaseURL.String(), false} + p := HTMLBodyExtParam{rc.BaseURL.String(), false, cfg.UrlParameter} if len(rc.Key) > 0 { p.HasMortyKey = true } @@ -982,9 +999,9 @@ func (rc *RequestConfig) ProxifyURI(uri []byte) (string, error) { morty_uri := u.String() if rc.Key == nil { - return fmt.Sprintf("./?mortyurl=%s%s", url.QueryEscape(morty_uri), fragment), nil + return fmt.Sprintf("./?%s=%s%s", cfg.UrlParameter, url.QueryEscape(morty_uri), fragment), nil } - return fmt.Sprintf("./?mortyhash=%s&mortyurl=%s%s", hash(morty_uri, rc.Key), url.QueryEscape(morty_uri), fragment), nil + return fmt.Sprintf("./?%s=%s&%s=%s%s", cfg.HashParameter, hash(morty_uri, rc.Key), cfg.UrlParameter, url.QueryEscape(morty_uri), fragment), nil } func inArray(b []byte, a [][]byte) bool { @@ -1042,11 +1059,13 @@ func (p *Proxy) serveMainPage(ctx *fasthttp.RequestCtx, statusCode int, err erro ctx.Write([]byte("")) } if p.Key == nil { - ctx.Write([]byte(` -
- Visit url: - -
`)) + p := HTMLMainPageFormParam{cfg.UrlParameter} + err := HTML_MAIN_PAGE_FORM.Execute(ctx, p) + if err != nil { + if cfg.Debug { + fmt.Println("failed to inject main page form", err) + } + } } else { ctx.Write([]byte(`

Warning! This instance does not support direct URL opening.

`)) } @@ -1063,6 +1082,8 @@ func main() { proxyenv := flag.Bool("proxyenv", false, "Use a HTTP proxy as set in the environment (HTTP_PROXY, HTTPS_PROXY and NO_PROXY). Overrides -proxy, -socks5, -ipv6.") proxy := flag.String("proxy", "", "Use the specified HTTP proxy (ie: '[user:pass@]hostname:port'). Overrides -socks5, -ipv6.") socks5 := flag.String("socks5", "", "Use a SOCKS5 proxy (ie: 'hostname:port'). Overrides -ipv6.") + urlParameter := flag.String("urlparam", cfg.UrlParameter, "user-defined requesting string URL parameter name (ie: '/?url=...' or '/?u=...')") + hashParameter := flag.String("hashparam", cfg.HashParameter, "user-defined requesting string HASH parameter name (ie: '/?hash=...' or '/?h=...')") version := flag.Bool("version", false, "Show version") flag.Parse() @@ -1072,6 +1093,8 @@ func main() { cfg.Debug = *debug cfg.RequestTimeout = *requestTimeout cfg.FollowRedirect = *followRedirect + cfg.UrlParameter = *urlParameter + cfg.HashParameter = *hashParameter if *version { fmt.Println(VERSION)