Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log IP on SSH authentication failure for Built-in SSH server #13150

Merged
merged 9 commits into from
Dec 8, 2020
14 changes: 10 additions & 4 deletions docs/content/doc/usage/fail2ban-setup.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,26 @@ menu:
**Remember that fail2ban is powerful and can cause lots of issues if you do it incorrectly, so make
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
`app.ini`, then you should be able to go off of `log/gitea.log`, which gives you something like this
on a bad authentication:
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
6543 marked this conversation as resolved.
Show resolved Hide resolved
on a bad authentication from the web or CLI using SSH or HTTP respectively:

```log
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`:

```ini
# gitea.conf
[Definition]
failregex = .*Failed authentication attempt for .* from <HOST>
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
ignoreregex =
```

Expand Down
2 changes: 1 addition & 1 deletion modules/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {

pkey, err := models.SearchPublicKeyByContent(strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
if err != nil {
log.Error("SearchPublicKeyByContent: %v", err)
log.Error("SearchPublicKeyByContent: %v Failed authentication attempt from %s", err, ctx.RemoteAddr())
return false
}

Expand Down
2 changes: 2 additions & 0 deletions routers/private/serv.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func ServCommand(ctx *macaron.Context) {
for _, verb := range ctx.QueryStrings("verb") {
if "git-upload-pack" == verb {
// 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{}{
"results": results,
"type": "ErrRepoNotExist",
Expand Down Expand Up @@ -317,6 +318,7 @@ func ServCommand(ctx *macaron.Context) {
userMode := perm.UnitAccessMode(unitType)

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{}{
"results": results,
"type": "ErrUnauthorized",
Expand Down
1 change: 1 addition & 0 deletions routers/repo/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func HTTP(ctx *context.Context) {

owner, err := models.GetUserByName(username)
if err != nil {
log.Error("Attempted access of unknown user from %s", ctx.RemoteAddr())
ctx.NotFoundOrServerError("GetUserByName", models.IsErrUserNotExist, err)
return
}
Expand Down