IPFilter.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using System.Net;
  2. using System.Text.RegularExpressions;
  3. using bitforum.Services;
  4. namespace bitforum.Middleware
  5. {
  6. public class IPFilter
  7. {
  8. private readonly RequestDelegate _next;
  9. private readonly ISetupService _setupService;
  10. public IPFilter(RequestDelegate next, ISetupService setupService)
  11. {
  12. _next = next;
  13. _setupService = setupService;
  14. }
  15. public async Task Invoke(HttpContext context)
  16. {
  17. var remoteIP = context.Connection.RemoteIpAddress;
  18. // IP가 허용되지 않으면 403 Forbidden 반환
  19. if (!IsIpAllowed(remoteIP))
  20. {
  21. context.Response.StatusCode = StatusCodes.Status403Forbidden;
  22. await context.Response.WriteAsync("Access Denied: Your IP is not allowed to access this resource.");
  23. return;
  24. }
  25. await _next(context);
  26. }
  27. private bool IsIpAllowed(IPAddress? remoteIP)
  28. {
  29. if (remoteIP == null)
  30. {
  31. return false;
  32. }
  33. var adminWhiteIpList = _setupService.GetConfig("admin_white_ip_list");
  34. var allowedIPs = string.IsNullOrWhiteSpace(adminWhiteIpList) ? new List<string>() : adminWhiteIpList.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries).Select(ip => ip.Trim()).ToList();
  35. // 허용된 IP가 없으면 기본적으로 모든 요청 허용
  36. if (!allowedIPs.Any())
  37. {
  38. return true;
  39. }
  40. var ipString = remoteIP.ToString();
  41. foreach (var allowedIP in allowedIPs)
  42. {
  43. if (allowedIP.Contains("*"))
  44. {
  45. var regex = "^" + Regex.Escape(allowedIP).Replace("\\*", ".*") + "$";
  46. if (Regex.IsMatch(ipString, regex))
  47. {
  48. return true;
  49. }
  50. }
  51. else if (allowedIP.Contains("-"))
  52. {
  53. var parts = allowedIP.Split('-');
  54. if (parts.Length == 2 && IPAddress.TryParse(parts[0].Trim(), out var startIp) && IPAddress.TryParse(parts[1].Trim(), out var endIp) && IsInRange(remoteIP, startIp, endIp))
  55. {
  56. return true;
  57. }
  58. }
  59. else if (IPAddress.TryParse(allowedIP, out var allowedAddress) && remoteIP.Equals(allowedAddress))
  60. {
  61. return true;
  62. }
  63. }
  64. return false;
  65. }
  66. private bool IsInRange(IPAddress IP, IPAddress startIP, IPAddress endIP)
  67. {
  68. var ipBytes = IP.GetAddressBytes();
  69. var startBytes = startIP.GetAddressBytes();
  70. var endBytes = endIP.GetAddressBytes();
  71. if (ipBytes.Length != startBytes.Length || ipBytes.Length != endBytes.Length)
  72. {
  73. return false;
  74. }
  75. for (int i = 0; i < ipBytes.Length; i++)
  76. {
  77. if (ipBytes[i] < startBytes[i] || ipBytes[i] > endBytes[i])
  78. {
  79. return false;
  80. }
  81. }
  82. return true;
  83. }
  84. }
  85. }