diff --git a/modules/private/internal.go b/modules/private/internal.go index 2ea516ba80..21e5c9a279 100644 --- a/modules/private/internal.go +++ b/modules/private/internal.go @@ -10,6 +10,8 @@ import ( "fmt" "net" "net/http" + "os" + "strings" "code.gitea.io/gitea/modules/httplib" "code.gitea.io/gitea/modules/json" @@ -18,13 +20,14 @@ import ( "code.gitea.io/gitea/modules/setting" ) -func newRequest(ctx context.Context, url, method string) *httplib.Request { +func newRequest(ctx context.Context, url, method, sourceIP string) *httplib.Request { if setting.InternalToken == "" { log.Fatal(`The INTERNAL_TOKEN setting is missing from the configuration file: %q. Ensure you are running in the correct environment or set the correct configuration file with -c.`, setting.CustomConf) } return httplib.NewRequest(url, method). SetContext(ctx). + Header("X-Real-IP", sourceIP). Header("Authorization", fmt.Sprintf("Bearer %s", setting.InternalToken)) } @@ -42,8 +45,16 @@ func decodeJSONError(resp *http.Response) *Response { return &res } +func getClientIP() string { + sshConnEnv := strings.TrimSpace(os.Getenv("SSH_CONNECTION")) + if len(sshConnEnv) == 0 { + return "127.0.0.1" + } + return strings.Fields(sshConnEnv)[0] +} + func newInternalRequest(ctx context.Context, url, method string) *httplib.Request { - req := newRequest(ctx, url, method).SetTLSClientConfig(&tls.Config{ + req := newRequest(ctx, url, method, getClientIP()).SetTLSClientConfig(&tls.Config{ InsecureSkipVerify: true, ServerName: setting.Domain, }) diff --git a/routers/private/internal.go b/routers/private/internal.go index e9cc20a77d..f8e451e80f 100644 --- a/routers/private/internal.go +++ b/routers/private/internal.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/web" "gitea.com/go-chi/binding" + chi_middleware "github.com/go-chi/chi/v5/middleware" ) // CheckInternalToken check internal token is set @@ -57,6 +58,9 @@ func Routes() *web.Route { r := web.NewRoute() r.Use(context.PrivateContexter()) r.Use(CheckInternalToken) + // Log the real ip address of the request from SSH is really helpful for diagnosing sometimes. + // Since internal API will be sent only from Gitea sub commands and it's under control (checked by InternalToken), we can trust the headers. + r.Use(chi_middleware.RealIP) r.Post("/ssh/authorized_keys", AuthorizedPublicKeyByContent) r.Post("/ssh/{id}/update/{repoid}", UpdatePublicKeyInRepo)