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:
Eric Lesiuta 2020-12-08 12:54:33 -05:00 committed by GitHub
parent 42354dfe45
commit abb9cffe4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 12 additions and 3 deletions

View File

@ -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 =
``` ```

View File

@ -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
} }

View File

@ -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",

View File

@ -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
} }