diff --git a/.gitignore b/.gitignore index 6307876..945c70e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -morty +yukari diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3f18409..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: go -sudo: false -go: - - 1.12.x -script: - # run tests on a standard platform - - OUT="$(go get -a)"; test -z "$OUT" || (echo "$OUT" && return 1) - - OUT="$(gofmt -l -d ./)"; test -z "$OUT" || (echo "$OUT" && return 1) - - go vet -v ./... - - go test -v ./... - - # build test for supported platforms - - GOOS=linux go build - - GOOS=darwin go build - - GOOS=freebsd go build - - GOOS=windows go build - - GOARCH=386 go build diff --git a/CHANGELOG.md b/CHANGELOG.md index 215b872..f380015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.2.1 - 2023.08.26 +Applied some suggestions from the issue tracker, and +rebrand this fork. + # v0.2.0 - 2018.05.28 Man page added diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index c1bd5ec..0000000 --- a/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -# STEP 1 build executable binary -FROM golang:1.14-alpine as builder - -WORKDIR $GOPATH/src/github.com/asciimoo/morty - -RUN apk add --no-cache git - -COPY . . -RUN go get -d -v -RUN gofmt -l ./ -#RUN go vet -v ./... -#RUN go test -v ./... -RUN go build . - -# STEP 2 build the image including only the binary -FROM alpine:3.12 - -EXPOSE 3000 - -RUN apk --no-cache add ca-certificates \ - && rm -f /var/cache/apk/* \ - && adduser -D -h /usr/local/morty -s /bin/false morty morty - -COPY --from=builder /go/src/github.com/asciimoo/morty/morty /usr/local/morty/morty - -USER morty - -ENV DEBUG=true - -ENTRYPOINT ["/usr/local/morty/morty"] diff --git a/Makefile b/Makefile index 369ccfb..e855f38 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ -APP_NAME=morty +all: build +bench: + go test -benchmem -bench . build: - docker rmi -f $(APP_NAME):latest - docker build -t $(APP_NAME) . - -run: - @echo "\n /!\ DO NOT use in production\n" - docker run --rm -t -i --net=host --name="$(APP_NAME)" $(APP_NAME) + go build -o yukari +clean: + rm -f yukari +test: + go test diff --git a/README.md b/README.md index 6b047fc..6eb89b4 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,10 @@ -# Morty +# Yukari -[![Build Status](https://travis-ci.org/asciimoo/morty.svg)](https://travis-ci.org/asciimoo/morty) -[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) -[![Docker Pulls](https://img.shields.io/docker/pulls/dalf/morty)](https://hub.docker.com/r/dalf/morty) +Web content sanitizer proxy as a service, fork of [MortyProxy](https://github.com/asciimoo/morty) with some suggestions from the issue tracker applied, named after [Yes, that Gap Youkai](https://en.touhouwiki.net/wiki/Yukari_Yakumo) -Web content sanitizer proxy as a service +Yukari rewrites web pages to exclude malicious HTML tags and attributes. It also replaces external resource references to prevent third party information leaks. -Morty rewrites web pages to exclude malicious HTML tags and attributes. It also replaces external resource references to prevent third party information leaks. - -The main goal of morty is to provide a result proxy for [searx](https://asciimoo.github.com/searx/), but it can be used as a standalone sanitizer service too. +The main goal of yukari is to provide a result proxy for [searx](https://asciimoo.github.com/searx/), but it can be used as a standalone sanitizer service too. Features: @@ -26,8 +22,8 @@ Features: Requirement: Go version 1.10 or higher. ``` -$ go install github.com/asciimoo/morty@latest -$ "$GOPATH/bin/morty" --help +$ go install marisa.chaotic.ninja/yukari@latest +$ "$GOPATH/bin/yukari" --help ``` ### Usage @@ -38,7 +34,7 @@ $ "$GOPATH/bin/morty" --help -followredirect Follow HTTP GET redirect -hashparam string - User-defined requesting string HASH parameter name (ie: '/?hash=...' or '/?h=...') (default "mortyhash") + User-defined requesting string HASH parameter name (ie: '/?hash=...' or '/?h=...') (default "yukarihash") -ipv6 Allow IPv6 HTTP requests (default true) -key string @@ -54,35 +50,24 @@ $ "$GOPATH/bin/morty" --help -timeout uint Request timeout (default 5) -urlparam string - User-defined requesting string URL parameter name (ie: '/?url=...' or '/?u=...') (default "mortyurl") + User-defined requesting string URL parameter name (ie: '/?url=...' or '/?u=...') (default "yukariurl") -version Show version ``` ### Environment variables -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`) +Yukari can additionally be configured using the following environment variables: +- `YUKARI_ADDRESS`: Listen address (default to `127.0.0.1:3000`) +- `YUKARI_KEY`: HMAC url validation key (base64 encoded) to prevent direct URL opening. Leave blank to disable validation. Use `openssl rand -base64 33` to generate. +- `YUKARI_URL_PARAM`: User-defined requesting string URL parameter name (ie: `/?url=...` or `/?u=...`) (default `yukariurl`) +- `YUKARI_HASH_PARAM`: User-defined requesting string HASH parameter name (ie: `/?hash=...` or `/?h=...`) (default `yukarihash`) - `DEBUG`: Enable/disable proxy and redirection logs (default to `true`). Set to `false` to disable. -### Docker - -``` -docker run -e DEBUG=false -e MORTY_ADDRESS=0.0.0.0:3000 dalf/morty -``` - -``` -docker run -e DEBUG=false dalf/morty -listen 0.0.0.0:3000 -``` - - ### Test ``` -$ cd "$GOPATH/src/github.com/asciimoo/morty" +$ cd "$GOPATH/src/marisa.chaotic.ninja/yukari" $ go test ``` @@ -90,11 +75,10 @@ $ go test ### Benchmark ``` -$ cd "$GOPATH/src/github.com/asciimoo/morty" +$ cd "$GOPATH/src/marisa.chaotic.ninja/yukari" $ go test -benchmem -bench . ``` ## Bugs - -Bugs or suggestions? Visit the [issue tracker](https://github.com/asciimoo/morty/issues). +Bugs or suggestions? Visit the [issue tracker](https://git.chaotic.ninja/yakumo.izuru/yukari/issues). diff --git a/config/config.go b/config/config.go index de547a1..7ce42b3 100644 --- a/config/config.go +++ b/config/config.go @@ -19,19 +19,19 @@ type Config struct { var DefaultConfig *Config func init() { - default_listen_addr := os.Getenv("MORTY_ADDRESS") + default_listen_addr := os.Getenv("YUKARI_ADDRESS") if default_listen_addr == "" { default_listen_addr = "127.0.0.1:3000" } - default_url_parameter := os.Getenv("MORTY_URL_PARAM") + default_url_parameter := os.Getenv("YUKARI_URL_PARAM") if default_url_parameter == "" { - default_url_parameter = "mortyurl" + default_url_parameter = "yukariurl" } - default_hash_parameter := os.Getenv("MORTY_HASH_PARAM") + default_hash_parameter := os.Getenv("YUKARI_HASH_PARAM") if default_hash_parameter == "" { - default_hash_parameter = "mortyhash" + default_hash_parameter = "yukarihash" } - default_key := os.Getenv("MORTY_KEY") + default_key := os.Getenv("YUKARI_KEY") DefaultConfig = &Config{ Debug: os.Getenv("DEBUG") != "false", ListenAddress: default_listen_addr, diff --git a/go.mod b/go.mod index 149503d..b7e62a4 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/asciimoo/morty +module marisa.chaotic.ninja/yukari go 1.14 diff --git a/morty.1 b/yukari.1 similarity index 77% rename from morty.1 rename to yukari.1 index d82d46c..5d65f5b 100644 --- a/morty.1 +++ b/yukari.1 @@ -1,16 +1,16 @@ -.TH MORTY "1" "2018" "morty" "User Commands" +.TH MORTY "1" "2018" "yukari" "User Commands" .SH NAME -morty \- Privacy aware web content sanitizer proxy as a service +yukari \- Privacy aware web content sanitizer proxy as a service .SH SYNOPSIS -.B morty +.B yukari .RI [ OPTIONS ] .br .SH DESCRIPTION -Morty rewrites web pages to exclude malicious HTML tags and attributes. It +Yukari rewrites web pages to exclude malicious HTML tags and attributes. It also replaces external resource references to prevent third party information leaks. .sp -The main goal of morty is to provide a result proxy for searx, but it can be +The main goal of yukari is to provide a result proxy for searx, but it can be used as a standalone sanitizer service too. .SH OPTIONS .HP @@ -35,10 +35,12 @@ Request timeout (default 2) Show version .SH BUGS Bugs or suggestions? Visit the issue tracker at -https://github.com/asciimoo/morty/issues. +https://git.chaotic.ninja/yakumo.izuru/yukari/issues. .SH SEE ALSO .BR searx (1) .SH LICENSE +Copyright 2023-present Izuru Yakumo +.br Copyright 2016-2018 Adam Tauber .br Copyright 2016 Alexandre Flament diff --git a/morty.go b/yukari.go similarity index 91% rename from morty.go rename to yukari.go index af90712..cc97659 100644 --- a/morty.go +++ b/yukari.go @@ -27,8 +27,8 @@ import ( "golang.org/x/net/html/charset" "golang.org/x/text/encoding" - "github.com/asciimoo/morty/config" - "github.com/asciimoo/morty/contenttype" + "marisa.chaotic.ninja/yukari/config" + "marisa.chaotic.ninja/yukari/contenttype" ) const ( @@ -195,13 +195,13 @@ type RequestConfig struct { type HTMLBodyExtParam struct { BaseURL string - HasMortyKey bool + HasYukariKey bool URLParamName string } type HTMLFormExtParam struct { BaseURL string - MortyHash string + YukariHash string URLParamName string HashParamName string } @@ -217,10 +217,10 @@ var HTML_HEAD_CONTENT_TYPE string = ` ` -var MORTY_HTML_PAGE_START string = ` +var YUKARI_HTML_PAGE_START string = ` -MortyProxy +YukariSukima `) if err != nil { @@ -355,7 +355,7 @@ func (p *Proxy) ProcessUri(ctx *fasthttp.RequestCtx, requestURIStr string, redir // Serve an intermediate page for protocols other than HTTP(S) if (parsedURI.Scheme != "http" && parsedURI.Scheme != "https") || strings.HasSuffix(parsedURI.Host, ".onion") { - p.serveExitMortyPage(ctx, parsedURI) + p.serveExitYukariPage(ctx, parsedURI) return } @@ -397,7 +397,7 @@ func (p *Proxy) ProcessUri(ctx *fasthttp.RequestCtx, requestURIStr string, redir loc := resp.Header.Peek("Location") if loc != nil { if p.FollowRedirect && ctx.IsGet() { - // GET method: Morty follows the redirect + // GET method: Yukari follows the redirect if redirectCount < MAX_REDIRECT_COUNT { if cfg.Debug { log.Println("follow redirect to", string(loc)) @@ -408,7 +408,7 @@ func (p *Proxy) ProcessUri(ctx *fasthttp.RequestCtx, requestURIStr string, redir } return } else { - // Other HTTP methods: Morty does NOT follow the redirect + // Other HTTP methods: Yukari does NOT follow the redirect rc := &RequestConfig{Key: p.Key, BaseURL: parsedURI} url, err := rc.ProxifyURI(loc) if err == nil { @@ -506,7 +506,7 @@ func (p *Proxy) ProcessUri(ctx *fasthttp.RequestCtx, requestURIStr string, redir if !rc.BodyInjected { p := HTMLBodyExtParam{rc.BaseURL.String(), false, cfg.UrlParameter} if len(rc.Key) > 0 { - p.HasMortyKey = true + p.HasYukariKey = true } err := HTML_BODY_EXTENSION.Execute(ctx, p) if err != nil { @@ -730,7 +730,7 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) { case "body": p := HTMLBodyExtParam{rc.BaseURL.String(), false, cfg.UrlParameter} if len(rc.Key) > 0 { - p.HasMortyKey = true + p.HasYukariKey = true } err := HTML_BODY_EXTENSION.Execute(out, p) if err != nil { @@ -978,7 +978,7 @@ func (rc *RequestConfig) ProxifyURI(uri []byte) (string, error) { fragment = "#" + u.Fragment } - // reset the fragment: it is not included in the mortyurl + // reset the fragment: it is not included in the yukariurl u.Fragment = "" // merge the URI with the document URI @@ -996,12 +996,12 @@ func (rc *RequestConfig) ProxifyURI(uri []byte) (string, error) { } // return full URI and fragment (if not empty) - morty_uri := u.String() + yukari_uri := u.String() if rc.Key == nil { - return fmt.Sprintf("./?%s=%s%s", cfg.UrlParameter, url.QueryEscape(morty_uri), fragment), nil + return fmt.Sprintf("./?%s=%s%s", cfg.UrlParameter, url.QueryEscape(yukari_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 + return fmt.Sprintf("./?%s=%s&%s=%s%s", cfg.HashParameter, hash(yukari_uri, rc.Key), cfg.UrlParameter, url.QueryEscape(yukari_uri), fragment), nil } func inArray(b []byte, a [][]byte) bool { @@ -1033,23 +1033,23 @@ func verifyRequestURI(uri, hashMsg, key []byte) bool { return hmac.Equal(h, mac.Sum(nil)) } -func (p *Proxy) serveExitMortyPage(ctx *fasthttp.RequestCtx, uri *url.URL) { +func (p *Proxy) serveExitYukariPage(ctx *fasthttp.RequestCtx, uri *url.URL) { ctx.SetContentType("text/html") ctx.SetStatusCode(403) - ctx.Write([]byte(MORTY_HTML_PAGE_START)) - ctx.Write([]byte("

You are about to exit MortyProxy

")) + ctx.Write([]byte(YUKARI_HTML_PAGE_START)) + ctx.Write([]byte("

You are about to exit YukariSukima

")) ctx.Write([]byte("

Following

")) ctx.Write([]byte(html.EscapeString(uri.String()))) ctx.Write([]byte("

the content of this URL will be NOT sanitized.

")) - ctx.Write([]byte(MORTY_HTML_PAGE_END)) + ctx.Write([]byte(YUKARI_HTML_PAGE_END)) } func (p *Proxy) serveMainPage(ctx *fasthttp.RequestCtx, statusCode int, err error) { ctx.SetContentType("text/html; charset=UTF-8") ctx.SetStatusCode(statusCode) - ctx.Write([]byte(MORTY_HTML_PAGE_START)) + ctx.Write([]byte(YUKARI_HTML_PAGE_START)) if err != nil { if cfg.Debug { log.Println("error:", err) @@ -1069,7 +1069,7 @@ func (p *Proxy) serveMainPage(ctx *fasthttp.RequestCtx, statusCode int, err erro } else { ctx.Write([]byte(`

Warning! This instance does not support direct URL opening.

`)) } - ctx.Write([]byte(MORTY_HTML_PAGE_END)) + ctx.Write([]byte(YUKARI_HTML_PAGE_END)) } func main() { diff --git a/morty_test.go b/yukari_test.go similarity index 94% rename from morty_test.go rename to yukari_test.go index 5928934..efba0d1 100644 --- a/morty_test.go +++ b/yukari_test.go @@ -27,17 +27,17 @@ var attrTestData []*AttrTestCase = []*AttrTestCase{ &AttrTestCase{ []byte("href"), []byte("./x"), - []byte(` href="./?mortyurl=http%3A%2F%2F127.0.0.1%2Fx"`), + []byte(` href="./?yukariurl=http%3A%2F%2F127.0.0.1%2Fx"`), }, &AttrTestCase{ []byte("src"), []byte("http://x.com/y"), - []byte(` src="./?mortyurl=http%3A%2F%2Fx.com%2Fy"`), + []byte(` src="./?yukariurl=http%3A%2F%2Fx.com%2Fy"`), }, &AttrTestCase{ []byte("action"), []byte("/z"), - []byte(` action="./?mortyurl=http%3A%2F%2F127.0.0.1%2Fz"`), + []byte(` action="./?yukariurl=http%3A%2F%2F127.0.0.1%2Fz"`), }, &AttrTestCase{ []byte("onclick"), @@ -107,11 +107,11 @@ var sanitizeUriTestData []*SanitizeURITestCase = []*SanitizeURITestCase{ var urlTestData []*StringTestCase = []*StringTestCase{ &StringTestCase{ "http://x.com/", - "./?mortyurl=http%3A%2F%2Fx.com%2F", + "./?yukariurl=http%3A%2F%2Fx.com%2F", }, &StringTestCase{ "http://a@x.com/", - "./?mortyurl=http%3A%2F%2Fa%40x.com%2F", + "./?yukariurl=http%3A%2F%2Fa%40x.com%2F", }, &StringTestCase{ "#a",