ShelfPlayer triggers Fail2ban bans via Nginx (multiple 401 errors on Audiobookshelf API endpoints from iOS)
Hello,
I'm experiencing an issue where using ShelfPlayer on iOS causes my Fail2ban jail (nginx-unauthorized) to ban my own IP on my Audiobookshelf server. The problem appears when ShelfPlayer tries to connect: several requests to /api endpoints return HTTP 401 errors in a short time window, which Fail2ban interprets as suspicious activity (like brute-force).
Here's an anonymized sample from my Nginx log (generated by my mobile connection):
xxx.yyy.zzz.www - - [25/Sep/2025:10:28:51 +0200] "GET /api/libraries HTTP/2.0" 401 12 - "ShelfPlayer/8.7.5 CFNetwork/3860.100.1 Darwin/25.0.0"
xxx.yyy.zzz.www - - [25/Sep/2025:10:28:51 +0200] "GET /api/items?... HTTP/2.0" 401 12 - "ShelfPlayer/8.7.5 CFNetwork/3860.100.1 Darwin/25.0.0"
Because my mobile IP changes frequently, whitelisting it is not a viable solution. This makes normal use of the app almost impossible, since I keep getting banned from my own server after a few failed attempts. The trigger seems to be ShelfPlayer failing authentication with multiple quick 401s, possibly due to automatic background sync or a session problem.
Can you review how ShelfPlayer handles authentication failures or suggest a workaround for users running Fail2ban on their Nginx proxy (especially when using dynamic IPs)? Is it possible for ShelfPlayer to limit repeated unauthenticated requests, or handle tokens/cookies differently to avoid bursts of 401s?
Thank you for your help—and for this app!
Please note: This message was written by an assistant (AI) based on all the technical details I provided, because I'm a French user and cannot express this issue in English myself.
Hello, I really need help here. I get banned from my fail2ban protection every day. 👋🏻
Hey,
This issue is caused by the new authorization system introduced in ABS 26.0. ShelfPlayer sends requests in parallel to speed up the UI. When the current access token expires, ABS returns a 401 error. ShelfPlayer then refreshes the token once and retries all the requests.
Currently, there's no limit on how many requests can be made in parallel. While this behavior is intentional, I agree it could be improved. I plan to look into adding a synchronization mechanism to limit concurrent requests, but implementing that will take additional time I don’t have at the moment.
In the meantime, I suggest exposing ABS on an additional subdomain (e.g., if abs.example.org is the main one, use abs2.example.org) and requiring header-based authorization while disabling Fail2Ban in NGINX. I use the following config:
if ($http_x_abc_authorization != "128_CHARACTER_OR_EVEN_MORE_SECRET") {
return 401;
}
Then, set the custom HTTP header X-ABC-Authorization in ShelfPlayer. As long as you choose a sufficiently long and secret value, the risk of unauthorized access is low. I realize this may not be the solution you were hoping for, but it should work securely until I have time to implement proper synchronization.
Hello @rasmuslos Thanks for your answer. I’ll into the solution you gave: use another domain for ShelfPlayer. Maybe it’ll work better than the solution I tried.