mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Log IP on SSH authentication failure for Built-in SSH server (#13150)
* Log IP on SSH authentication failure fixes https://github.com/go-gitea/gitea/issues/13094 * include string 'Failed authentication attempt' in error * update fail2ban docs also match failed authentication over command line * better logging of authentication errors with IP addresses * format ... Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		| @@ -20,18 +20,24 @@ sure to test this before relying on it so you don't lock yourself out.** | |||||||
|  |  | ||||||
| Gitea returns an HTTP 200 for bad logins in the web logs, but if you have logging options on in | Gitea returns an HTTP 200 for bad logins in the web logs, but if you have logging options on in | ||||||
| `app.ini`, then you should be able to go off of `log/gitea.log`, which gives you something like this | `app.ini`, then you should be able to go off of `log/gitea.log`, which gives you something like this | ||||||
| on a bad authentication: | on a bad authentication from the web or CLI using SSH or HTTP respectively: | ||||||
|  |  | ||||||
| ```log | ```log | ||||||
| 2018/04/26 18:15:54 [I] Failed authentication attempt for user from xxx.xxx.xxx.xxx | 2018/04/26 18:15:54 [I] Failed authentication attempt for user from xxx.xxx.xxx.xxx | ||||||
| ``` | ``` | ||||||
|  | ```log | ||||||
|  | 2020/10/15 16:05:09 modules/ssh/ssh.go:188:publicKeyHandler() [E] SearchPublicKeyByContent: public key does not exist [id: 0] Failed authentication attempt from xxx.xxx.xxx.xxx | ||||||
|  | ``` | ||||||
|  | ```log | ||||||
|  | 2020/10/15 16:08:44 ...s/context/context.go:204:HandleText() [E] invalid credentials from xxx.xxx.xxx.xxx | ||||||
|  | ``` | ||||||
|  |  | ||||||
| Add our filter in `/etc/fail2ban/filter.d/gitea.conf`: | Add our filter in `/etc/fail2ban/filter.d/gitea.conf`: | ||||||
|  |  | ||||||
| ```ini | ```ini | ||||||
| # gitea.conf | # gitea.conf | ||||||
| [Definition] | [Definition] | ||||||
| failregex =  .*Failed authentication attempt for .* from <HOST> | failregex =  .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST> | ||||||
| ignoreregex = | ignoreregex = | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|   | |||||||
| @@ -186,7 +186,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool { | |||||||
|  |  | ||||||
| 	pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key)))) | 	pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key)))) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("SearchPublicKeyByContent: %v", err) | 		log.Error("SearchPublicKeyByContent: %v Failed authentication attempt from %s", err, ctx.RemoteAddr()) | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -132,6 +132,7 @@ func ServCommand(ctx *macaron.Context) { | |||||||
| 			for _, verb := range ctx.QueryStrings("verb") { | 			for _, verb := range ctx.QueryStrings("verb") { | ||||||
| 				if "git-upload-pack" == verb { | 				if "git-upload-pack" == verb { | ||||||
| 					// User is fetching/cloning a non-existent repository | 					// User is fetching/cloning a non-existent repository | ||||||
|  | 					log.Error("Failed authentication attempt (cannot find repository: %s/%s) from %s", results.OwnerName, results.RepoName, ctx.RemoteAddr()) | ||||||
| 					ctx.JSON(http.StatusNotFound, map[string]interface{}{ | 					ctx.JSON(http.StatusNotFound, map[string]interface{}{ | ||||||
| 						"results": results, | 						"results": results, | ||||||
| 						"type":    "ErrRepoNotExist", | 						"type":    "ErrRepoNotExist", | ||||||
| @@ -317,6 +318,7 @@ func ServCommand(ctx *macaron.Context) { | |||||||
| 			userMode := perm.UnitAccessMode(unitType) | 			userMode := perm.UnitAccessMode(unitType) | ||||||
|  |  | ||||||
| 			if userMode < mode { | 			if userMode < mode { | ||||||
|  | 				log.Error("Failed authentication attempt for %s with key %s (not authorized to %s %s/%s) from %s", user.Name, key.Name, modeString, ownerName, repoName, ctx.RemoteAddr()) | ||||||
| 				ctx.JSON(http.StatusUnauthorized, map[string]interface{}{ | 				ctx.JSON(http.StatusUnauthorized, map[string]interface{}{ | ||||||
| 					"results": results, | 					"results": results, | ||||||
| 					"type":    "ErrUnauthorized", | 					"type":    "ErrUnauthorized", | ||||||
|   | |||||||
| @@ -102,6 +102,7 @@ func HTTP(ctx *context.Context) { | |||||||
|  |  | ||||||
| 	owner, err := models.GetUserByName(username) | 	owner, err := models.GetUserByName(username) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | 		log.Error("Attempted access of unknown user from %s", ctx.RemoteAddr()) | ||||||
| 		ctx.NotFoundOrServerError("GetUserByName", models.IsErrUserNotExist, err) | 		ctx.NotFoundOrServerError("GetUserByName", models.IsErrUserNotExist, err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user