规则判断
This commit is contained in:
+3
-2
@@ -6,8 +6,9 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum SecurityRulePassTypeEnum {
|
||||
REJECT(0, "reject"),
|
||||
ALLOW(1, "allow")
|
||||
DENY(-1, "DENY"),
|
||||
ALLOW(1, "allow"),
|
||||
NONE(0, "none")
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package org.dromara.neutrinoproxy.server.dal;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.dromara.neutrinoproxy.server.dal.entity.SecurityRule;
|
||||
import org.dromara.neutrinoproxy.server.dal.entity.SecurityRuleDO;
|
||||
|
||||
public interface SecurityRuleMapper extends BaseMapper<SecurityRule> {
|
||||
public interface SecurityRuleMapper extends BaseMapper<SecurityRuleDO> {
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class SecurityGroupDO {
|
||||
* 启用状态
|
||||
* {@link EnableStatusEnum}
|
||||
*/
|
||||
private Integer enable;
|
||||
private EnableStatusEnum enable;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
|
||||
+14
-13
@@ -10,7 +10,6 @@ import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.neutrinoproxy.server.constant.EnableStatusEnum;
|
||||
import org.dromara.neutrinoproxy.server.constant.SecurityRulePassTypeEnum;
|
||||
import org.noear.solon.core.util.IpUtil;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@@ -18,7 +17,7 @@ import java.util.Date;
|
||||
@ToString
|
||||
@Accessors(chain = true)
|
||||
@TableName("security_rule")
|
||||
public class SecurityRule {
|
||||
public class SecurityRuleDO {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@@ -68,7 +67,7 @@ public class SecurityRule {
|
||||
* 启用状态
|
||||
* {@link EnableStatusEnum}
|
||||
*/
|
||||
private Integer enable;
|
||||
private EnableStatusEnum enable;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@@ -83,16 +82,16 @@ public class SecurityRule {
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
public boolean allow(String ip) {
|
||||
public SecurityRulePassTypeEnum allow(String ip) {
|
||||
|
||||
// 被判断的IP地址为空,不允许访问
|
||||
// 被判断的IP地址为空,不做判断
|
||||
if (StrUtil.isEmpty(ip)) {
|
||||
return false;
|
||||
return SecurityRulePassTypeEnum.NONE;
|
||||
}
|
||||
|
||||
// 没有规则,默认允许访问
|
||||
if (StrUtil.isEmpty(rule)) {
|
||||
return true;
|
||||
return SecurityRulePassTypeEnum.ALLOW;
|
||||
}
|
||||
|
||||
// ipv6只适配单ip形式
|
||||
@@ -107,14 +106,16 @@ public class SecurityRule {
|
||||
|
||||
// 单个ip,ipv6在此步已处理,后面不需要额外判断ipv6的情况
|
||||
if (rule.matches("(\\d+\\.){3}\\d+") || isIpv6) {
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW && rule.equals(ip);
|
||||
if (rule.equals(ip)) {
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW ? SecurityRulePassTypeEnum.ALLOW : SecurityRulePassTypeEnum.DENY;
|
||||
}
|
||||
}
|
||||
|
||||
// 范围类型
|
||||
if (rule.matches("(\\d+\\.){3}\\d+-(\\d+\\.){3}\\d+")) {
|
||||
String[] ipRange = rule.split("-");
|
||||
if (ipRange[0].compareTo(ip) <= 0 && ip.compareTo(ipRange[1]) <= 0) {
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW;
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW ? SecurityRulePassTypeEnum.ALLOW : SecurityRulePassTypeEnum.DENY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,18 +125,18 @@ public class SecurityRule {
|
||||
Long beginIp = Ipv4Util.getBeginIpLong(netIp[0], Integer.valueOf(netIp[1]));
|
||||
Long endIp = Ipv4Util.getEndIpLong(netIp[0], Integer.valueOf(netIp[1]));
|
||||
if (beginIp <= ipLong && ipLong <= endIp) {
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW;
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW ? SecurityRulePassTypeEnum.ALLOW : SecurityRulePassTypeEnum.DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (rule.equalsIgnoreCase("ALL") || rule.equals("0.0.0.0") || rule.equals("0..0.0.0/0")) {
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW;
|
||||
return passType == SecurityRulePassTypeEnum.ALLOW ? SecurityRulePassTypeEnum.ALLOW : SecurityRulePassTypeEnum.DENY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 都没有匹配到,默认放行
|
||||
return true;
|
||||
// 都没有匹配到
|
||||
return SecurityRulePassTypeEnum.NONE;
|
||||
}
|
||||
|
||||
}
|
||||
+9
-6
@@ -1,6 +1,11 @@
|
||||
package org.dromara.neutrinoproxy.server.proxy.core;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.neutrinoproxy.core.Constants;
|
||||
import org.dromara.neutrinoproxy.core.ProxyMessage;
|
||||
@@ -8,11 +13,6 @@ import org.dromara.neutrinoproxy.server.constant.NetworkProtocolEnum;
|
||||
import org.dromara.neutrinoproxy.server.proxy.domain.VisitorChannelAttachInfo;
|
||||
import org.dromara.neutrinoproxy.server.service.FlowReportService;
|
||||
import org.dromara.neutrinoproxy.server.util.ProxyUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import org.noear.solon.Solon;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -62,8 +62,11 @@ public class TcpVisitorChannelHandler extends SimpleChannelInboundHandler<ByteBu
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
Channel visitorChannel = ctx.channel();
|
||||
InetSocketAddress sa = (InetSocketAddress) visitorChannel.localAddress();
|
||||
Channel cmdChannel = ProxyUtil.getCmdChannelByServerPort(sa.getPort());
|
||||
|
||||
// 判断IP是否在该端口绑定的安全组允许的规则内
|
||||
|
||||
|
||||
Channel cmdChannel = ProxyUtil.getCmdChannelByServerPort(sa.getPort());
|
||||
if (null == cmdChannel) {
|
||||
// 该端口还没有代理客户端
|
||||
ctx.channel().close();
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package org.dromara.neutrinoproxy.server.service;
|
||||
|
||||
import cn.hutool.cache.Cache;
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.apache.ibatis.solon.annotation.Db;
|
||||
import org.dromara.neutrinoproxy.server.constant.EnableStatusEnum;
|
||||
import org.dromara.neutrinoproxy.server.constant.SecurityRulePassTypeEnum;
|
||||
import org.dromara.neutrinoproxy.server.dal.SecurityGroupMapper;
|
||||
import org.dromara.neutrinoproxy.server.dal.SecurityRuleMapper;
|
||||
import org.dromara.neutrinoproxy.server.dal.entity.SecurityGroupDO;
|
||||
import org.dromara.neutrinoproxy.server.dal.entity.SecurityRuleDO;
|
||||
import org.noear.solon.annotation.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
public class SecurityGroupService {
|
||||
|
||||
@Db
|
||||
private SecurityGroupMapper securityGroupMapper;
|
||||
|
||||
@Db
|
||||
private SecurityRuleMapper securityRuleMapper;
|
||||
|
||||
private Map<Integer, SecurityGroupDO> securityGroupMap = new ConcurrentHashMap<>();
|
||||
|
||||
// 允许通过控制的缓存,缓存类型最近最久未使用缓存,容量100,超时时间5分钟
|
||||
private Cache<String, Boolean> ipAllowControlCache = CacheUtil.newLRUCache(100, 1000 * 60 * 5);
|
||||
|
||||
public void init() {
|
||||
List<SecurityGroupDO> groupDOList = securityGroupMapper.selectList(Wrappers.lambdaQuery(SecurityGroupDO.class));
|
||||
groupDOList.forEach(securityGroupDO -> securityGroupMap.put(securityGroupDO.getId(), securityGroupDO));
|
||||
}
|
||||
|
||||
public boolean judgeAllow(String ip, Integer groupId) {
|
||||
|
||||
SecurityGroupDO groupDO = securityGroupMap.get(groupId);
|
||||
if (groupDO == null || groupDO.getEnable() == EnableStatusEnum.DISABLE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String judgeAllowMapKey = ip + groupId;
|
||||
if (ipAllowControlCache.containsKey(judgeAllowMapKey)) {
|
||||
return ipAllowControlCache.get(judgeAllowMapKey);
|
||||
}
|
||||
|
||||
List<SecurityRuleDO> ruleDOList = securityRuleMapper.selectList(Wrappers.lambdaQuery(SecurityRuleDO.class)
|
||||
.eq(SecurityRuleDO::getGroupId, groupId)
|
||||
.orderByAsc(SecurityRuleDO::getPriority)
|
||||
);
|
||||
Boolean allow = null;
|
||||
for (SecurityRuleDO ruleDO : ruleDOList) {
|
||||
SecurityRulePassTypeEnum passType = ruleDO.allow(ip);
|
||||
if (passType == SecurityRulePassTypeEnum.ALLOW) {
|
||||
allow = true;
|
||||
break;
|
||||
}
|
||||
if (passType == SecurityRulePassTypeEnum.DENY) {
|
||||
allow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allow == null) {
|
||||
allow = true;
|
||||
}
|
||||
|
||||
// 当前IP没有匹配到任何一条规则,则放行
|
||||
ipAllowControlCache.put(judgeAllowMapKey, allow);
|
||||
|
||||
return allow;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user