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
}
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()
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 {
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})

View file

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

View file

@ -18,7 +18,7 @@ import (
"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 == "" {
return ""
}
@ -30,10 +30,16 @@ func ProxifyRelativeURL(router *mux.Router, mediaURL string) string {
mac := hmac.New(sha256.New, config.Opts.MediaProxyPrivateKey())
mac.Write([]byte(mediaURL))
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)))
}
func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string) string {
func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string, feedSiteURL ...string) string {
if mediaURL == "" {
return ""
}
@ -42,7 +48,7 @@ func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string) string {
return proxifyURLWithCustomProxy(mediaURL, customProxyURL)
}
proxifiedUrl := ProxifyRelativeURL(router, mediaURL)
proxifiedUrl := ProxifyRelativeURL(router, mediaURL, feedSiteURL...)
scheme := "http"
if config.Opts.HTTPS {
scheme = "https"

View file

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

View file

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

View file

@ -29,6 +29,7 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
encodedDigest := request.RouteStringParam(r, "encodedDigest")
encodedURL := request.RouteStringParam(r, "encodedURL")
encodedReferer := request.RouteStringParam(r, "encodedReferer")
if encodedURL == "" {
html.BadRequest(w, r, errors.New("no URL provided"))
return
@ -46,6 +47,8 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
return
}
decodeReferer, _ := base64.URLEncoding.DecodeString(encodedReferer)
mac := hmac.New(sha256.New, config.Opts.MediaProxyPrivateKey())
mac.Write(decodedURL)
expectedMAC := mac.Sum(nil)
@ -87,6 +90,10 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
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.
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/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}/{encodedReferer}", handler.mediaProxy).Name("proxyWithReferer").Methods(http.MethodGet)
uiRouter.HandleFunc("/entry/bookmark/{entryID}", handler.toggleBookmark).Name("toggleBookmark").Methods(http.MethodPost)
// Share pages.