Skip to content

Commit 4964756

Browse files
zeripath6543wxiaoguang
committed
Provide configuration to allow camo-media proxying (go-gitea#12802)
* Provide configuration to allow camo-media proxying Fix go-gitea#916 Signed-off-by: Andrew Thornton <[email protected]> Co-authored-by: 6543 <[email protected]> Co-authored-by: wxiaoguang <[email protected]>
1 parent 1a8e34a commit 4964756

File tree

6 files changed

+133
-1
lines changed

6 files changed

+133
-1
lines changed

custom/conf/app.example.ini

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,23 @@ INTERNAL_TOKEN=
393393
;; This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
394394
;SUCCESSFUL_TOKENS_CACHE_SIZE = 20
395395

396+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
397+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
398+
[camo]
399+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
400+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
401+
;;
402+
;; At the moment we only support images
403+
;;
404+
;; if the camo is enabled
405+
;ENABLED = false
406+
;; url to a camo image proxy, it **is required** if camo is enabled.
407+
;SERVER_URL =
408+
;; HMAC to encode urls with, it **is required** if camo is enabled.
409+
;HMAC_KEY =
410+
;; Set to true to use camo for https too lese only non https urls are proxyed
411+
;ALLWAYS = false
412+
396413
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
397414
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
398415
[oauth2]

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,14 @@ Certain queues have defaults that override the defaults set in `[queue]` (this o
512512
- spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~``
513513
- off - do not check password complexity
514514
- `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed.
515-
- `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
515+
- `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
516+
517+
## Camo (`camo`)
518+
519+
- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
520+
- `SERVER_URL`: **<empty>**: url of camo server, it **is required** if camo is enabled.
521+
- `HMAC_KEY`: **<empty>**: Provide the HMAC key for encoding urls, it **is required** if camo is enabled.
522+
- `ALLWAYS`: **false**: Set to true to use camo for https too lese only non https urls are proxyed
516523

517524
## OpenID (`openid`)
518525

modules/markup/camo.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package markup
6+
7+
import (
8+
"crypto/hmac"
9+
"crypto/sha1"
10+
"encoding/base64"
11+
"net/url"
12+
"strings"
13+
14+
"code.gitea.io/gitea/modules/setting"
15+
"code.gitea.io/gitea/modules/util"
16+
)
17+
18+
// CamoEncode encodes a lnk to fit with the go-camo and camo proxy links. The purposes of camo-proxy are:
19+
// 1. Allow accessing "http://" images on a HTTPS site by using the "https://" URLs provided by camo-proxy.
20+
// 2. Hide the visitor's real IP (protect privacy) when accessing external images.
21+
func CamoEncode(link string) string {
22+
if strings.HasPrefix(link, setting.Camo.ServerURL) {
23+
return link
24+
}
25+
26+
mac := hmac.New(sha1.New, []byte(setting.Camo.HMACKey))
27+
_, _ = mac.Write([]byte(link)) // hmac does not return errors
28+
macSum := b64encode(mac.Sum(nil))
29+
encodedURL := b64encode([]byte(link))
30+
31+
return util.URLJoin(setting.Camo.ServerURL, macSum, encodedURL)
32+
}
33+
34+
func b64encode(data []byte) string {
35+
return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=")
36+
}
37+
38+
func camoHandleLink(link string) string {
39+
if setting.Camo.Enabled {
40+
lnkURL, err := url.Parse(link)
41+
if err == nil && lnkURL.IsAbs() && !strings.HasPrefix(link, setting.AppURL) &&
42+
(setting.Camo.Allways || lnkURL.Scheme != "https") {
43+
return CamoEncode(link)
44+
}
45+
}
46+
return link
47+
}

modules/markup/camo_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package markup
6+
7+
import (
8+
"testing"
9+
10+
"code.gitea.io/gitea/modules/setting"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestCamoHandleLink(t *testing.T) {
16+
setting.AppURL = "https://gitea.com"
17+
// Test media proxy
18+
setting.Camo.Enabled = true
19+
setting.Camo.ServerURL = "https://image.proxy"
20+
setting.Camo.HMACKey = "geheim"
21+
22+
assert.Equal(t,
23+
"https://gitea.com/img.jpg",
24+
camoHandleLink("https://gitea.com/img.jpg"))
25+
assert.Equal(t,
26+
"https://testimages.org/img.jpg",
27+
camoHandleLink("https://testimages.org/img.jpg"))
28+
assert.Equal(t,
29+
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
30+
camoHandleLink("http://testimages.org/img.jpg"))
31+
32+
setting.Camo.Allways = true
33+
assert.Equal(t,
34+
"https://gitea.com/img.jpg",
35+
camoHandleLink("https://gitea.com/img.jpg"))
36+
assert.Equal(t,
37+
"https://image.proxy/tkdlvmqpbIr7SjONfHNgEU622y0/aHR0cHM6Ly90ZXN0aW1hZ2VzLm9yZy9pbWcuanBn",
38+
camoHandleLink("https://testimages.org/img.jpg"))
39+
assert.Equal(t,
40+
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
41+
camoHandleLink("http://testimages.org/img.jpg"))
42+
43+
// Restore previous settings
44+
setting.Camo.Enabled = false
45+
}

modules/markup/html.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ func visitNode(ctx *RenderContext, procs, textProcs []processor, node *html.Node
385385

386386
attr.Val = util.URLJoin(prefix, attr.Val)
387387
}
388+
attr.Val = camoHandleLink(attr.Val)
388389
node.Attr[i] = attr
389390
}
390391
} else if node.Data == "a" {

modules/setting/setting.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ var (
197197
PasswordCheckPwn bool
198198
SuccessfulTokensCacheSize int
199199

200+
Camo = struct {
201+
Enabled bool
202+
ServerURL string `ini:"SERVER_URL"`
203+
HMACKey string `ini:"HMAC_KEY"`
204+
Allways bool
205+
}{}
206+
200207
// UI settings
201208
UI = struct {
202209
ExplorePagingNum int
@@ -984,6 +991,14 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
984991
log.Fatal("Failed to map API settings: %v", err)
985992
} else if err = Cfg.Section("metrics").MapTo(&Metrics); err != nil {
986993
log.Fatal("Failed to map Metrics settings: %v", err)
994+
} else if err = Cfg.Section("camo").MapTo(&Camo); err != nil {
995+
log.Fatal("Failed to map Camo settings: %v", err)
996+
}
997+
998+
if Camo.Enabled {
999+
if Camo.ServerURL == "" || Camo.HMACKey == "" {
1000+
log.Fatal(`Camo settings require "SERVER_URL" and HMAC_KEY`)
1001+
}
9871002
}
9881003

9891004
u := *appURL

0 commit comments

Comments
 (0)