From 79ceab82b693ebd5c0aed4a95e31809293ad3f18 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Fri, 30 Dec 2022 22:45:34 -0500 Subject: [PATCH 1/3] added ip whitelisting --- .../Settings/InstanceSettings.cs | 1 + .../Middlewares/IpWhitelistingMiddleware.cs | 68 +++++++++++++++++++ src/BirdsiteLive/Startup.cs | 5 ++ 3 files changed, 74 insertions(+) create mode 100644 src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs diff --git a/src/BirdsiteLive.Common/Settings/InstanceSettings.cs b/src/BirdsiteLive.Common/Settings/InstanceSettings.cs index 0f701ff..4526c1b 100644 --- a/src/BirdsiteLive.Common/Settings/InstanceSettings.cs +++ b/src/BirdsiteLive.Common/Settings/InstanceSettings.cs @@ -16,5 +16,6 @@ public int FailingFollowerCleanUpThreshold { get; set; } = -1; public int UserCacheCapacity { get; set; } + public string IpWhiteListing { get; set; } } } diff --git a/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs b/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs new file mode 100644 index 0000000..1846d8f --- /dev/null +++ b/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs @@ -0,0 +1,68 @@ +using BirdsiteLive.Common.Settings; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; + +namespace BirdsiteLive.Middlewares +{ + public class IpWhitelistingMiddleware + { + private readonly RequestDelegate _next; + private readonly ILogger _logger; + private readonly byte[][] _safelist; + private readonly bool _ipWhitelistingSet; + + public IpWhitelistingMiddleware( + RequestDelegate next, + ILogger logger, + InstanceSettings instanceSettings) + { + if (!string.IsNullOrWhiteSpace(instanceSettings.IpWhiteListing)) + { + var ips = instanceSettings.IpWhiteListing.Split(';'); + _safelist = new byte[ips.Length][]; + for (var i = 0; i < ips.Length; i++) + { + _safelist[i] = IPAddress.Parse(ips[i]).GetAddressBytes(); + } + _ipWhitelistingSet = true; + } + + _next = next; + _logger = logger; + } + + public async Task Invoke(HttpContext context) + { + //if (context.Request.Method != HttpMethod.Get.Method) + if (_ipWhitelistingSet) + { + var remoteIp = context.Connection.RemoteIpAddress; + _logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp); + + var bytes = remoteIp.GetAddressBytes(); + var badIp = true; + foreach (var address in _safelist) + { + if (address.SequenceEqual(bytes)) + { + badIp = false; + break; + } + } + + if (badIp) + { + _logger.LogWarning("Forbidden Request from Remote IP address: {RemoteIp}", remoteIp); + context.Response.StatusCode = (int)HttpStatusCode.NotFound; + return; + } + } + + await _next.Invoke(context); + } + } +} \ No newline at end of file diff --git a/src/BirdsiteLive/Startup.cs b/src/BirdsiteLive/Startup.cs index 16c7ee4..e088a56 100644 --- a/src/BirdsiteLive/Startup.cs +++ b/src/BirdsiteLive/Startup.cs @@ -8,6 +8,7 @@ using BirdsiteLive.Common.Structs; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Postgres.DataAccessLayers; using BirdsiteLive.DAL.Postgres.Settings; +using BirdsiteLive.Middlewares; using BirdsiteLive.Models; using BirdsiteLive.Twitter; using BirdsiteLive.Twitter.Tools; @@ -18,6 +19,7 @@ using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; namespace BirdsiteLive { @@ -132,6 +134,9 @@ namespace BirdsiteLive app.UseAuthorization(); + var instanceSettings = Configuration.GetSection("Instance").Get(); + app.UseMiddleware(instanceSettings); + app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( From 0c2acc3d7afba6110063f62326ffbd241ec0fa2f Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Fri, 30 Dec 2022 22:49:19 -0500 Subject: [PATCH 2/3] better ip parsing --- src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs b/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs index 1846d8f..e09ad27 100644 --- a/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs +++ b/src/BirdsiteLive/Middlewares/IpWhitelistingMiddleware.cs @@ -1,4 +1,5 @@ using BirdsiteLive.Common.Settings; +using BirdsiteLive.Domain.Tools; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System.Linq; @@ -22,7 +23,7 @@ namespace BirdsiteLive.Middlewares { if (!string.IsNullOrWhiteSpace(instanceSettings.IpWhiteListing)) { - var ips = instanceSettings.IpWhiteListing.Split(';'); + var ips = PatternsParser.Parse(instanceSettings.IpWhiteListing); _safelist = new byte[ips.Length][]; for (var i = 0; i < ips.Length; i++) { @@ -37,7 +38,6 @@ namespace BirdsiteLive.Middlewares public async Task Invoke(HttpContext context) { - //if (context.Request.Method != HttpMethod.Get.Method) if (_ipWhitelistingSet) { var remoteIp = context.Connection.RemoteIpAddress; From 8bbbe037c412193bbd06e5f93f34cb241cc4af38 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Fri, 30 Dec 2022 22:52:11 -0500 Subject: [PATCH 3/3] added IP whitelisting --- VARIABLES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/VARIABLES.md b/VARIABLES.md index 2ef0cdf..990e045 100644 --- a/VARIABLES.md +++ b/VARIABLES.md @@ -51,6 +51,7 @@ If both whitelisting and blacklisting are set, only the whitelisting will be act * `Instance:FailingTwitterUserCleanUpThreshold` (default: 700) set the max allowed errors (due to a banned/deleted/private account) from a Twitter Account retrieval before auto-removal. (by default an account is called every 15 mins) * `Instance:FailingFollowerCleanUpThreshold` (default: 30000) set the max allowed errors from a Follower (Fediverse) Account before auto-removal. (often due to account suppression, instance issues, etc) * `Instance:UserCacheCapacity` (default: 10000) set the caching limit of the Twitter User retrieval. Must be higher than the number of synchronized accounts on the instance. +* `Instance:IpWhiteListing` IP Whitelisting (separated by `;`), prevent usage of the instance from other IPs than those provided (if provided). # Docker Compose full example