Skip to content

Commit 5fc8c99

Browse files
committed
#296 port io.netty.handler.ipfilter
1 parent 58a82a0 commit 5fc8c99

14 files changed

+715
-2
lines changed

DotNetty.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) Microsoft. All rights reserved.&#xD;
7575
Licensed under the MIT license. See LICENSE file in the project root for full license information.</s:String>
7676
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
77+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
7778
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
7879
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
7980
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>

src/DotNetty.Common/DotNetty.Common.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
3636
<PackageReference Include="System.Diagnostics.Contracts" Version="4.3.0" />
3737
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
38+
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
3839
</ItemGroup>
3940
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
4041
<Reference Include="System.Runtime" />
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace DotNetty.Common.Internal
5+
{
6+
using System.Net;
7+
using System.Net.Sockets;
8+
9+
public class SocketUtils
10+
{
11+
public static IPAddress AddressByName(string hostname)
12+
{
13+
if (string.IsNullOrEmpty(hostname))
14+
{
15+
bool isIPv6Supported = Socket.OSSupportsIPv6;
16+
if (isIPv6Supported)
17+
{
18+
return IPAddress.IPv6Loopback;
19+
}
20+
else
21+
{
22+
return IPAddress.Loopback;
23+
}
24+
}
25+
if (hostname == "0.0.0.0")
26+
{
27+
return IPAddress.Any;
28+
}
29+
if (hostname == "::0" || hostname == "::")
30+
{
31+
return IPAddress.IPv6Any;
32+
}
33+
if (IPAddress.TryParse(hostname, out IPAddress parseResult))
34+
{
35+
return parseResult;
36+
}
37+
IPHostEntry hostEntry = Dns.GetHostEntryAsync(hostname).Result;
38+
return hostEntry.AddressList[0];
39+
}
40+
}
41+
}

src/DotNetty.Handlers/DotNetty.Handlers.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<?xml version="1.0" encoding="utf-8"?><Project Sdk="Microsoft.NET.Sdk">
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project Sdk="Microsoft.NET.Sdk">
23
<PropertyGroup Label="NuGet">
34
<TargetFrameworks>netstandard1.3;net45</TargetFrameworks>
45
<IsPackable>true</IsPackable>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
namespace DotNetty.Handlers.IPFilter
4+
{
5+
using System;
6+
using System.Net;
7+
using System.Threading.Tasks;
8+
using DotNetty.Transport.Channels;
9+
10+
/// <summary>
11+
/// This class provides the functionality to either accept or reject new <see cref="IChannel"/>s
12+
/// based on their IP address.
13+
/// You should inherit from this class if you would like to implement your own IP-based filter. Basically you have to
14+
/// implement <see cref="Accept"/> to decided whether you want to accept or reject
15+
/// a connection from the remote address.
16+
/// Furthermore overriding <see cref="ChannelRejected"/> gives you the
17+
/// flexibility to respond to rejected (denied) connections. If you do not want to send a response, just have it return
18+
/// null. Take a look at <see cref="RuleBasedIPFilter"/> for details.
19+
/// </summary>
20+
public abstract class AbstractRemoteAddressFilter<T>: ChannelHandlerAdapter where T:EndPoint
21+
{
22+
public override void ChannelRegistered(IChannelHandlerContext ctx)
23+
{
24+
this.HandleNewChannel(ctx);
25+
ctx.FireChannelRegistered();
26+
}
27+
28+
public override void ChannelActive(IChannelHandlerContext ctx)
29+
{
30+
if (!this.HandleNewChannel(ctx))
31+
{
32+
throw new ArgumentException(nameof(ctx),"cannot determine to accept or reject a channel: " + ctx.Channel);
33+
}
34+
else
35+
{
36+
ctx.FireChannelActive();
37+
}
38+
}
39+
40+
bool HandleNewChannel(IChannelHandlerContext ctx)
41+
{
42+
var remoteAddress = (T)ctx.Channel.RemoteAddress;
43+
44+
// If the remote address is not available yet, defer the decision.
45+
if (remoteAddress == null)
46+
{
47+
return false;
48+
}
49+
50+
// No need to keep this handler in the pipeline anymore because the decision is going to be made now.
51+
// Also, this will prevent the subsequent events from being handled by this handler.
52+
ctx.Pipeline.Remove(this);
53+
if (this.Accept(ctx, remoteAddress))
54+
{
55+
this.ChannelAccepted(ctx, remoteAddress);
56+
}
57+
else
58+
{
59+
Task rejectedTask = this.ChannelRejected(ctx, remoteAddress);
60+
if (rejectedTask != null)
61+
{
62+
rejectedTask.ContinueWith(_ =>
63+
{
64+
ctx.CloseAsync();
65+
});
66+
}
67+
else
68+
{
69+
ctx.CloseAsync();
70+
}
71+
}
72+
return true;
73+
}
74+
75+
/// <summary>
76+
/// This method is called immediately after a <see cref="IChannel"/> gets registered.
77+
/// </summary>
78+
/// <returns>Return true if connections from this IP address and port should be accepted. False otherwise.</returns>
79+
protected abstract bool Accept(IChannelHandlerContext ctx, T remoteAddress);
80+
81+
/// <summary>
82+
/// This method is called if <paramref name="remoteAddress"/> gets accepted by
83+
/// <see cref="Accept"/>. You should override it if you would like to handle
84+
/// (e.g. respond to) accepted addresses.
85+
/// </summary>
86+
protected virtual void ChannelAccepted(IChannelHandlerContext ctx, T remoteAddress) { }
87+
88+
89+
/// <summary>
90+
/// This method is called if <paramref name="remoteAddress"/> gets rejected by
91+
/// <see cref="Accept"/>. You should override it if you would like to handle
92+
/// (e.g. respond to) rejected addresses.
93+
/// <returns>
94+
/// A <see cref="Task"/> if you perform I/O operations, so that
95+
/// the <see cref="IChannel"/> can be closed once it completes. Null otherwise.
96+
/// </returns>
97+
/// </summary>
98+
protected virtual Task ChannelRejected(IChannelHandlerContext ctx, T remoteAddress)
99+
{
100+
return null;
101+
}
102+
}
103+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
namespace DotNetty.Handlers.IPFilter
4+
{
5+
using System.Net;
6+
7+
/// <summary>
8+
/// Implement this interface to create new rules.
9+
/// </summary>
10+
public interface IIPFilterRule
11+
{
12+
/// <summary>
13+
/// This method should return true if remoteAddress is valid according to your criteria. False otherwise.
14+
/// </summary>
15+
bool Matches(IPEndPoint remoteAddress);
16+
17+
/// <summary>
18+
/// This method should return <see cref="IPFilterRuleType.Accept"/> if all
19+
/// <see cref="Matches"/> for which <see cref="Matches"/>
20+
/// returns true should the accepted. If you want to exclude all of those IP addresses then
21+
/// <see cref="IPFilterRuleType.Reject"/> should be returned.
22+
/// </summary>
23+
IPFilterRuleType RuleType { get; }
24+
}
25+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace DotNetty.Handlers.IPFilter
5+
{
6+
/// <summary>
7+
/// Used in <see cref="IIPFilterRule"/> to decide if a matching IP Address should be allowed or denied to connect.
8+
/// </summary>
9+
public enum IPFilterRuleType
10+
{
11+
Accept,
12+
Reject
13+
}
14+
}

0 commit comments

Comments
 (0)