@@ -2,6 +2,7 @@ package route
2
2
3
3
import (
4
4
"net/http"
5
+ "strings"
5
6
6
7
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
7
8
"github.com/IceWhaleTech/CasaOS-Gateway/service"
@@ -18,6 +19,38 @@ func NewGatewayRoute(management *service.Management) *GatewayRoute {
18
19
}
19
20
}
20
21
22
+ // the function is to ensure the request source IP is correct.
23
+ func rewriteRequestSourceIP (r * http.Request ) {
24
+ // we may receive two kinds of requests. a request from reverse proxy. a request from client.
25
+
26
+ // in reverse proxy, X-Forwarded-For will like
27
+ // `X-Forwarded-For:[192.168.6.102]`(normal)
28
+ // `X-Forwarded-For:[::1, 192.168.6.102]`(hacked) Note: the ::1 is inject by attacker.
29
+ // `X-Forwarded-For:[::1]`(normal or hacked) local request. But it from browser have JWT. So we can and need to verify it
30
+ // `X-Forwarded-For:[::1,::1]`(normal or hacked) attacker can build the request to bypass the verification.
31
+ // But in the case. the remoteAddress should be the real ip. So we can use remoteAddress to verify it.
32
+
33
+ ipList := strings .Split (r .Header .Get ("X-Forwarded-For" ), "," )
34
+
35
+ r .Header .Del ("X-Forwarded-For" )
36
+ r .Header .Del ("X-Real-IP" )
37
+
38
+ // Note: the X-Forwarded-For depend the correct config from reverse proxy.
39
+ // otherwise the X-Forwarded-For may be empty.
40
+ remoteIP := r .RemoteAddr [:strings .LastIndex (r .RemoteAddr , ":" )]
41
+ if len (ipList ) > 0 && (remoteIP == "127.0.0.1" || remoteIP == "::1" ) {
42
+ // to process the request from reverse proxy
43
+
44
+ // in reverse proxy, X-Forwarded-For will container multiple IPs.
45
+ // if the request is from reverse proxy, the r.RemoteAddr will be 127.0.0.1.
46
+ // So we need get ip from X-Forwarded-For
47
+ r .Header .Add ("X-Forwarded-For" , ipList [len (ipList )- 1 ])
48
+ }
49
+ // to process the request from client.
50
+ // the gateway will add the X-Forwarded-For to request header.
51
+ // So we didn't need to add it.
52
+ }
53
+
21
54
func (g * GatewayRoute ) GetRoute () * http.ServeMux {
22
55
gatewayMux := http .NewServeMux ()
23
56
gatewayMux .HandleFunc ("/" , func (w http.ResponseWriter , r * http.Request ) {
@@ -36,6 +69,10 @@ func (g *GatewayRoute) GetRoute() *http.ServeMux {
36
69
return
37
70
}
38
71
72
+ // to fix https://github.com/IceWhaleTech/CasaOS/security/advisories/GHSA-32h8-rgcj-2g3c#event-102885
73
+ // API V1 and V2 both read ip from request header. So the fix is effective for v1 and v2.
74
+ rewriteRequestSourceIP (r )
75
+
39
76
proxy .ServeHTTP (w , r )
40
77
})
41
78
0 commit comments