package cc.blynk.server.admin.http.handlers;
import cc.blynk.utils.ParseUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.ipfilter.AbstractRemoteAddressFilter;
import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.Set;
/**
* The Blynk Project.
* Created by Dmitriy Dumanskiy.
* Created on 16.12.15.
*/
@ChannelHandler.Sharable
public class IpFilterHandler extends AbstractRemoteAddressFilter<InetSocketAddress> {
private static final Logger log = LogManager.getLogger(IpFilterHandler.class);
private final Set<String> allowedIPs = new HashSet<>();
private final Set<IpSubnetFilterRule> rules = new HashSet<>();
public IpFilterHandler(String[] allowedIPs) {
if (allowedIPs == null) {
return;
}
for (String allowedIP : allowedIPs) {
if (allowedIP.contains("/")) {
String[] split = allowedIP.split("/");
String ip = split[0];
int cidr = ParseUtil.parseInt(split[1]);
this.rules.add(new IpSubnetFilterRule(ip, cidr, IpFilterRuleType.ACCEPT));
} else {
this.allowedIPs.add(allowedIP);
}
}
}
@Override
public boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) {
if (allowedIPs.size() == 0 && rules.size() == 0) {
return false;
}
if (allowedIPs.contains(remoteAddress.getAddress().getHostAddress())) {
return true;
}
if (remoteAddress.getAddress() instanceof Inet6Address) {
log.error("Look like you are trying to connect with IPv6 : {}. While in 'allowed.administrator.ips' " +
"you are using IPv4.",
remoteAddress.getAddress().getHostAddress());
return false;
}
for (IpSubnetFilterRule rule : rules) {
if (rule.matches(remoteAddress)) {
return true;
}
}
return false;
}
}