天天看點

Netty中基于ip的白名單或者黑名單機制示例RuleBasedIpFilter簡介示例測試

使用Netty 4.1.23版本需要用到白名單機制,發現網上很多資料都是介紹IpFilterRuleHandler,仔細一看4.x版本中找不到這個,而5.x又不被推薦使用,是以仔細檢視官方4.x文檔發現有個RuleBasedIpFilter可以使用。

RuleBasedIpFilter簡介

RuleBasedIpFilter是基于ip的過濾器,可以自定義哪些ip或者ip範圍允許通過或者被阻止。因為預設情況下,如果不添加任何IpSubnetFilterRule, RuleBasedIpFilter就會允許所有ip。如果我們使用白名單機制,要麼繼承RuleBasedIpFilter類,重寫accept方法,要不在RuleBasedIpFilter, 添加一個rejectAll,并将該rejectAll放在數組的最後。

public class RuleBasedIpFilter extends AbstractRemoteAddressFilter<InetSocketAddress> {
    private final IpFilterRule[] rules;

    public RuleBasedIpFilter(IpFilterRule... rules) {
        if (rules == null) {
            throw new NullPointerException("rules");
        } else {
            this.rules = rules;
        }
    }

    protected boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) throws Exception {
        IpFilterRule[] var3 = this.rules;
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            IpFilterRule rule = var3[var5];
            if (rule == null) {
                break;
            }

            if (rule.matches(remoteAddress)) {
                return rule.ruleType() == IpFilterRuleType.ACCEPT;
            }
        }

        return true;
    }
}
           

示例

示例比較簡單,啟動一個server,使用StringDecoder和StringEncoder。

public class NettyServer {

    public void bind() throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch)
                            throws IOException {

                        IpSubnetFilterRule rule1 = new IpSubnetFilterRule("192.168.119.1", 24, IpFilterRuleType.ACCEPT);
                        IpSubnetFilterRule rule2 = new IpSubnetFilterRule("127.0.0.1", 32, IpFilterRuleType.REJECT);
                        IpFilterRule rejectAll = new IpFilterRule() {
                            @Override
                            public boolean matches(InetSocketAddress remoteAddress) {
                                return true;
                            }

                            @Override
                            public IpFilterRuleType ruleType() {
                                return IpFilterRuleType.REJECT;
                            }
                        };
                        RuleBasedIpFilter filter = new RuleBasedIpFilter(rule1, rejectAll );
                        ch.pipeline().addLast("ipFilter", filter);
                        ch.pipeline().addLast("encoder", new StringEncoder());
                        ch.pipeline().addLast("decoder", new StringDecoder());
                        ch.pipeline().addLast(new StringHandler());

                    }
                });
        //我本機有多個ip,啟動時不綁定特定ip, 這樣才能友善白名單測試
        b.bind(NettyConstant.PORT).sync();
        System.out.println("Netty server start successfully: " + (NettyConstant.PORT));
    }

    public static void main(String[] args) throws Exception {
        new NettyServer().bind();
    }
}

           

測試

使用telnet 127.0.0.1 8080 會被自動斷開

使用telnet 192.168.119.1 8080 可以正确連接配接上(我機器的ip是192.168.119.1,白名單允許192.168.119.x連接配接,但是不允許127.0.0.1連接配接).

讀者需要更新允許的ip, 因為我本機是192.168.119.1,是以允許192.168.119.x, 如果你的ip不是這個範圍,需要修改代碼,否則就不能連接配接上8080.

Netty中基于ip的白名單或者黑名單機制示例RuleBasedIpFilter簡介示例測試