feat: referer spoof

Signed-off-by: SouthFox <master@southfox.me>
This commit is contained in:
SouthFox 2024-07-23 16:08:18 +08:00
parent b683756d8e
commit 3e802f1c87
7 changed files with 30 additions and 12 deletions

View file

@ -36,7 +36,7 @@ func (h *handler) getEntryFromBuilder(w http.ResponseWriter, r *http.Request, b
return return
} }
entry.Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entry.Content) entry.Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entry.Content, entry.Feed.SiteURL)
proxyOption := config.Opts.MediaProxyMode() proxyOption := config.Opts.MediaProxyMode()
for i := range entry.Enclosures { for i := range entry.Enclosures {
@ -164,7 +164,7 @@ func (h *handler) findEntries(w http.ResponseWriter, r *http.Request, feedID int
} }
for i := range entries { for i := range entries {
entries[i].Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entries[i].Content) entries[i].Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entries[i].Content, entries[i].Feed.SiteURL)
} }
json.OK(w, r, &entriesResponse{Total: count, Entries: entries}) json.OK(w, r, &entriesResponse{Total: count, Entries: entries})

View file

@ -16,13 +16,17 @@ import (
type urlProxyRewriter func(router *mux.Router, url string) string type urlProxyRewriter func(router *mux.Router, url string) string
func RewriteDocumentWithRelativeProxyURL(router *mux.Router, htmlDocument string) string { func RewriteDocumentWithRelativeProxyURL(router *mux.Router, htmlDocument string, feedSiteURL ...string) string {
return genericProxyRewriter(router, ProxifyRelativeURL, htmlDocument) proxifyFunction := func(router *mux.Router, mediaURL string) string {
return ProxifyRelativeURL(router, mediaURL, feedSiteURL...)
} }
func RewriteDocumentWithAbsoluteProxyURL(router *mux.Router, host, htmlDocument string) string { return genericProxyRewriter(router, proxifyFunction, htmlDocument)
}
func RewriteDocumentWithAbsoluteProxyURL(router *mux.Router, host, htmlDocument string, feedSiteURL ...string) string {
proxifyFunction := func(router *mux.Router, url string) string { proxifyFunction := func(router *mux.Router, url string) string {
return ProxifyAbsoluteURL(router, host, url) return ProxifyAbsoluteURL(router, host, url, feedSiteURL...)
} }
return genericProxyRewriter(router, proxifyFunction, htmlDocument) return genericProxyRewriter(router, proxifyFunction, htmlDocument)
} }

View file

@ -18,7 +18,7 @@ import (
"miniflux.app/v2/internal/config" "miniflux.app/v2/internal/config"
) )
func ProxifyRelativeURL(router *mux.Router, mediaURL string) string { func ProxifyRelativeURL(router *mux.Router, mediaURL string, feedSiteURL ...string) string {
if mediaURL == "" { if mediaURL == "" {
return "" return ""
} }
@ -30,10 +30,16 @@ func ProxifyRelativeURL(router *mux.Router, mediaURL string) string {
mac := hmac.New(sha256.New, config.Opts.MediaProxyPrivateKey()) mac := hmac.New(sha256.New, config.Opts.MediaProxyPrivateKey())
mac.Write([]byte(mediaURL)) mac.Write([]byte(mediaURL))
digest := mac.Sum(nil) digest := mac.Sum(nil)
if len(feedSiteURL) > 0 {
referer := feedSiteURL[0]
return route.Path(router, "proxyWithReferer", "encodedDigest", base64.URLEncoding.EncodeToString(digest), "encodedURL", base64.URLEncoding.EncodeToString([]byte(mediaURL)), "encodedReferer", base64.URLEncoding.EncodeToString([]byte(referer)))
}
return route.Path(router, "proxy", "encodedDigest", base64.URLEncoding.EncodeToString(digest), "encodedURL", base64.URLEncoding.EncodeToString([]byte(mediaURL))) return route.Path(router, "proxy", "encodedDigest", base64.URLEncoding.EncodeToString(digest), "encodedURL", base64.URLEncoding.EncodeToString([]byte(mediaURL)))
} }
func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string) string { func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string, feedSiteURL ...string) string {
if mediaURL == "" { if mediaURL == "" {
return "" return ""
} }
@ -42,7 +48,7 @@ func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string) string {
return proxifyURLWithCustomProxy(mediaURL, customProxyURL) return proxifyURLWithCustomProxy(mediaURL, customProxyURL)
} }
proxifiedUrl := ProxifyRelativeURL(router, mediaURL) proxifiedUrl := ProxifyRelativeURL(router, mediaURL, feedSiteURL...)
scheme := "http" scheme := "http"
if config.Opts.HTTPS { if config.Opts.HTTPS {
scheme = "https" scheme = "https"

View file

@ -57,8 +57,8 @@ func (f *funcMap) Map() template.FuncMap {
"noescape": func(str string) template.HTML { "noescape": func(str string) template.HTML {
return template.HTML(str) return template.HTML(str)
}, },
"proxyFilter": func(data string) string { "proxyFilter": func(data string, feedSiteURL ...string) string {
return mediaproxy.RewriteDocumentWithRelativeProxyURL(f.router, data) return mediaproxy.RewriteDocumentWithRelativeProxyURL(f.router, data, feedSiteURL...)
}, },
"proxyURL": func(link string) string { "proxyURL": func(link string) string {
mediaProxyMode := config.Opts.MediaProxyMode() mediaProxyMode := config.Opts.MediaProxyMode()

View file

@ -205,7 +205,7 @@
{{ end }} {{ end }}
{{end}} {{end}}
{{ if .user }} {{ if .user }}
{{ noescape (proxyFilter .entry.Content) }} {{ noescape (proxyFilter .entry.Content .entry.Feed.SiteURL) }}
{{ else }} {{ else }}
{{ noescape .entry.Content }} {{ noescape .entry.Content }}
{{ end }} {{ end }}

View file

@ -29,6 +29,7 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
encodedDigest := request.RouteStringParam(r, "encodedDigest") encodedDigest := request.RouteStringParam(r, "encodedDigest")
encodedURL := request.RouteStringParam(r, "encodedURL") encodedURL := request.RouteStringParam(r, "encodedURL")
encodedReferer := request.RouteStringParam(r, "encodedReferer")
if encodedURL == "" { if encodedURL == "" {
html.BadRequest(w, r, errors.New("no URL provided")) html.BadRequest(w, r, errors.New("no URL provided"))
return return
@ -46,6 +47,8 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
return return
} }
decodeReferer, _ := base64.URLEncoding.DecodeString(encodedReferer)
mac := hmac.New(sha256.New, config.Opts.MediaProxyPrivateKey()) mac := hmac.New(sha256.New, config.Opts.MediaProxyPrivateKey())
mac.Write(decodedURL) mac.Write(decodedURL)
expectedMAC := mac.Sum(nil) expectedMAC := mac.Sum(nil)
@ -87,6 +90,10 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
return return
} }
if decodeReferer != nil {
req.Header.Add("Referer", string(decodeReferer))
}
// Note: User-Agent HTTP header is omitted to avoid being blocked by bot protection mechanisms. // Note: User-Agent HTTP header is omitted to avoid being blocked by bot protection mechanisms.
req.Header.Add("Connection", "close") req.Header.Add("Connection", "close")

View file

@ -103,6 +103,7 @@ func Serve(router *mux.Router, store *storage.Storage, pool *worker.Pool) {
uiRouter.HandleFunc("/entry/enclosure/{enclosureID}/save-progression", handler.saveEnclosureProgression).Name("saveEnclosureProgression").Methods(http.MethodPost) uiRouter.HandleFunc("/entry/enclosure/{enclosureID}/save-progression", handler.saveEnclosureProgression).Name("saveEnclosureProgression").Methods(http.MethodPost)
uiRouter.HandleFunc("/entry/download/{entryID}", handler.fetchContent).Name("fetchContent").Methods(http.MethodPost) uiRouter.HandleFunc("/entry/download/{entryID}", handler.fetchContent).Name("fetchContent").Methods(http.MethodPost)
uiRouter.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", handler.mediaProxy).Name("proxy").Methods(http.MethodGet) uiRouter.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", handler.mediaProxy).Name("proxy").Methods(http.MethodGet)
uiRouter.HandleFunc("/proxy/{encodedDigest}/{encodedURL}/{encodedReferer}", handler.mediaProxy).Name("proxyWithReferer").Methods(http.MethodGet)
uiRouter.HandleFunc("/entry/bookmark/{entryID}", handler.toggleBookmark).Name("toggleBookmark").Methods(http.MethodPost) uiRouter.HandleFunc("/entry/bookmark/{entryID}", handler.toggleBookmark).Name("toggleBookmark").Methods(http.MethodPost)
// Share pages. // Share pages.