The next generation of the Teknik Services. Written in ASP.NET. https://www.teknik.io/
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

RequestHelper.cs 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using Microsoft.AspNetCore.Http;
  2. using System;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. namespace Teknik.Utilities
  6. {
  7. public static class RequestHelper
  8. {
  9. // based on http://www.grantburton.com/2008/11/30/fix-for-incorrect-ip-addresses-in-wordpress-comments/
  10. public static string ClientIPFromRequest(this HttpRequest request, bool skipPrivate)
  11. {
  12. foreach (var item in s_HeaderItems)
  13. {
  14. var ipString = request.Headers[item.Key].ToString();
  15. if (String.IsNullOrEmpty(ipString))
  16. continue;
  17. if (item.Split)
  18. {
  19. foreach (var ip in ipString.Split(','))
  20. if (ValidIP(ip, skipPrivate))
  21. return ip;
  22. }
  23. else
  24. {
  25. if (ValidIP(ipString, skipPrivate))
  26. return ipString;
  27. }
  28. }
  29. return request.Host.Value;
  30. }
  31. private static bool ValidIP(string ip, bool skipPrivate)
  32. {
  33. IPAddress ipAddr;
  34. ip = ip == null ? String.Empty : ip.Trim();
  35. if (0 == ip.Length
  36. || false == IPAddress.TryParse(ip, out ipAddr)
  37. || (ipAddr.AddressFamily != AddressFamily.InterNetwork
  38. && ipAddr.AddressFamily != AddressFamily.InterNetworkV6))
  39. return false;
  40. if (skipPrivate && ipAddr.AddressFamily == AddressFamily.InterNetwork)
  41. {
  42. var addr = IpRange.AddrToUInt64(ipAddr);
  43. foreach (var range in s_PrivateRanges)
  44. {
  45. if (range.Encompasses(addr))
  46. return false;
  47. }
  48. }
  49. return true;
  50. }
  51. /// <summary>
  52. /// Provides a simple class that understands how to parse and
  53. /// compare IP addresses (IPV4) ranges.
  54. /// </summary>
  55. private sealed class IpRange
  56. {
  57. private readonly UInt64 _start;
  58. private readonly UInt64 _end;
  59. public IpRange(string startStr, string endStr)
  60. {
  61. _start = ParseToUInt64(startStr);
  62. _end = ParseToUInt64(endStr);
  63. }
  64. public static UInt64 AddrToUInt64(IPAddress ip)
  65. {
  66. var ipBytes = ip.GetAddressBytes();
  67. UInt64 value = 0;
  68. foreach (var abyte in ipBytes)
  69. {
  70. value <<= 8; // shift
  71. value += abyte;
  72. }
  73. return value;
  74. }
  75. public static UInt64 ParseToUInt64(string ipStr)
  76. {
  77. var ip = IPAddress.Parse(ipStr);
  78. return AddrToUInt64(ip);
  79. }
  80. public bool Encompasses(UInt64 addrValue)
  81. {
  82. return _start <= addrValue && addrValue <= _end;
  83. }
  84. public bool Encompasses(IPAddress addr)
  85. {
  86. var value = AddrToUInt64(addr);
  87. return Encompasses(value);
  88. }
  89. };
  90. private static readonly IpRange[] s_PrivateRanges =
  91. new IpRange[] {
  92. new IpRange("0.0.0.0","2.255.255.255"),
  93. new IpRange("10.0.0.0","10.255.255.255"),
  94. new IpRange("127.0.0.0","127.255.255.255"),
  95. new IpRange("169.254.0.0","169.254.255.255"),
  96. new IpRange("172.16.0.0","172.31.255.255"),
  97. new IpRange("192.0.2.0","192.0.2.255"),
  98. new IpRange("192.168.0.0","192.168.255.255"),
  99. new IpRange("255.255.255.0","255.255.255.255")
  100. };
  101. /// <summary>
  102. /// Describes a header item (key) and if it is expected to be
  103. /// a comma-delimited string
  104. /// </summary>
  105. private sealed class HeaderItem
  106. {
  107. public readonly string Key;
  108. public readonly bool Split;
  109. public HeaderItem(string key, bool split)
  110. {
  111. Key = key;
  112. Split = split;
  113. }
  114. }
  115. // order is in trust/use order top to bottom
  116. private static readonly HeaderItem[] s_HeaderItems =
  117. new HeaderItem[] {
  118. new HeaderItem("HTTP_CLIENT_IP",false),
  119. new HeaderItem("HTTP_X_FORWARDED_FOR",true),
  120. new HeaderItem("HTTP_X_FORWARDED",false),
  121. new HeaderItem("HTTP_X_CLUSTER_CLIENT_IP",false),
  122. new HeaderItem("HTTP_FORWARDED_FOR",false),
  123. new HeaderItem("HTTP_FORWARDED",false),
  124. new HeaderItem("HTTP_VIA",false),
  125. new HeaderItem("REMOTE_ADDR",false)
  126. };
  127. }
  128. }