Commit e641932a authored by wutu's avatar wutu

构建基础的iptables 底层服务接口

parent 2a792feb
......@@ -8,11 +8,18 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import top.ninwoo.utils.entity.ChainEntity;
import top.ninwoo.utils.entity.ChainType;
import top.ninwoo.utils.entity.DockerContainer;
import top.ninwoo.utils.service.DockerService;
import top.ninwoo.utils.service.OVSService;
import top.ninwoo.utils.service.OvsDockerService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试嵌入式Docker的服务接口
* @Author joliu
......@@ -83,6 +90,72 @@ public class InDockerTests {
System.out.println(result);
}
@Test
public void testParseIptablesDetail() {
/**
* Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
* 0 0 DROP all -- * * 10.1.100.3 0.0.0.0/0
*
* Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
*
* Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
*/
Map<String, List<ChainEntity>> map = new HashMap<>();
map.put("INPUT", new ArrayList<>());
map.put("FORWARD", new ArrayList<>());
map.put("OUTPUT", new ArrayList<>());
String result = "";
result = dockerService.execInDocker(dockerContainer1.getId(), new String[]{"iptables", "-I", "INPUT", "-s", "10.1.100.3", "-j", "DROP"});
System.out.println(result);
result = dockerService.execInDocker(dockerContainer1.getId(), new String[]{"iptables", "-vnL"});
String[] lines = result.split("\n");
ChainEntity.Builder builder = ChainEntity.builder();
String key = "";
for (int i = 0; i < lines.length; i++) {
if(lines[i].startsWith("Chain INPUT")) {
builder = ChainEntity.builder().type(ChainType.INPUT);
key = "INPUT";
i++;
continue;
} else if(lines[i].startsWith("Chain FORWARD")) {
builder = ChainEntity.builder().type(ChainType.FORWARD);
key = "FORWARD";
i++;
continue;
} else if(lines[i].startsWith("Chain OUTPUT")) {
builder = ChainEntity.builder().type(ChainType.OUTPUT);
key = "OUTPUT";
i++;
continue;
}
if("".equals(lines[i])) {
continue;
}
String[] s = lines[i].replaceAll(" +", " ").trim().split(" ");
ChainEntity chain;
if(s.length == 9) {
chain = builder.pkts(Long.parseLong(s[0]))
.bytes(Long.parseLong(s[1]))
.target(s[2])
.prot(s[3])
.opt(s[4])
.in(s[5])
.out(s[6])
.source(s[7])
.destination(s[8])
.build();
map.get(key).add(chain);
}
}
System.out.println(result);
}
@After
public void close() {
// 清除Docker
......
package top.ninwoo.utils.entity;
/**
* @Author joliu
* @Description iptables chain的实体类
* @Date Create in 下午10:43 2019/10/28
*/
public class ChainEntity {
// TODO: 亟待实现的一个类
private long pkts;
private long bytes;
private String target;
private String prot;
private String in;
private String out;
private String source;
private String destination;
private ChainType type;
private ChainEntity() {
}
private ChainEntity(Builder builder) {
this.pkts = builder.pkts;
this.bytes = builder.bytes;
this.destination = builder.destination;
this.in = builder.in;
this.out = builder.out;
this.prot = builder.prot;
this.source = builder.source;
this.target = builder.target;
this.type = builder.type;
}
public static class Builder {
private long pkts;
private long bytes;
private String target;
private String prot;
private String in;
private String out;
private String source;
private String destination;
private String opt;
private ChainType type;
public Builder() {
}
public String opt() {
return this.opt;
}
public Builder opt(String opt) {
this.opt = opt;
return this;
}
public long pkts() {
return this.pkts;
}
public Builder pkts(long pkts) {
this.pkts = pkts;
return this;
}
public long bytes() {
return this.bytes;
}
public Builder bytes(long bytes) {
this.bytes = bytes;
return this;
}
public String target() {
return this.target;
}
public Builder target(String target) {
this.target = target;
return this;
}
public String prot() {
return this.prot;
}
public Builder prot(String prot) {
this.prot = prot;
return this;
}
public String source() {
return this.source;
}
public Builder source(String source) {
this.source = source;
return this;
}
public String in() {
return this.in;
}
public Builder in(String in) {
this.in = in;
return this;
}
public String out() {
return this.out;
}
public Builder out(String out) {
this.out = out;
return this;
}
public String destination() {
return this.destination;
}
public Builder destination(String destination) {
this.destination = destination;
return this;
}
public ChainType type() {
return this.type;
}
public Builder type(ChainType type) {
this.type = type;
return this;
}
public ChainEntity build() {
return new ChainEntity(this);
}
}
public static Builder builder() {
return new Builder();
}
@Override
public String toString() {
return "ChainEntity{" +
"pkts=" + pkts +
", bytes=" + bytes +
", target='" + target + '\'' +
", prot='" + prot + '\'' +
", in='" + in + '\'' +
", out='" + out + '\'' +
", source='" + source + '\'' +
", destination='" + destination + '\'' +
", type=" + type +
'}';
}
}
package top.ninwoo.utils.entity;
/**
* @Author joliu
* @Description iptables Chain的类型
* @Date Create in 下午10:47 2019/10/28
*/
public enum ChainType {
INPUT("INPUT"), FORWARD("FORWARD"), OUTPUT("OUTPUT");
private String name;
ChainType(String name) {
this.name = name;
}
@Override
public String toString() {
return this.name;
}
}
package top.ninwoo.utils.service.impl;
/**
* @Author joliu
* @Description Docker内部的服务接口
* @Date Create in 下午10:04 2019/10/28
*/
public interface DockerInternalNetworkService {
// 网络拦截
/**
* 最基础的一个实现,功能也最单一
* iptables -I INPUT -s 172.17.0.1 -j DROP
* 后续需要扩展多种实现方案
* @param containerId
* @param destinationIp
* @return iptables 的条目
*/
int drop(String containerId, String destinationIp);
/**
* 取消拦截,这里可能需要涉及到上一条记录的id
* @param containerId
*/
void cancelDrop(String containerId);
// 网络转发
int forward(String containerId, String targetIp, String nextIp);
// 网络限速
int qos();
}
......@@ -210,4 +210,6 @@ public class DockerServiceImpl implements DockerService, InitializingBean {
String result = dockerUtils.execInDocker(containerId, args);
return result;
}
// 下边是基于iptables的服务接口
}
package top.ninwoo.utils.util;
import top.ninwoo.utils.entity.ChainEntity;
import top.ninwoo.utils.entity.ChainType;
import java.util.List;
import java.util.Map;
/**
* @Author joliu
* @Description
* @Date Create in 下午10:37 2019/10/28
*/
public interface IptablesUtils {
Map<String, List<ChainEntity>> showIptablesDetail(String containerId);
String addIptable(String containerId, String kind, ChainType chainType, String source, String destination, String policy);
// 添加一个iptables项
// 删除一个iptables项
// 查看iptables条目
}
package top.ninwoo.utils.util.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import top.ninwoo.utils.entity.ChainEntity;
import top.ninwoo.utils.entity.ChainType;
import top.ninwoo.utils.util.DockerUtils;
import top.ninwoo.utils.util.IptablesUtils;
import top.ninwoo.utils.util.Utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author joliu
* @Description
* @Date Create in 上午11:42 2019/10/29
*/
@Utils
public class IptablesUtilsImpl implements IptablesUtils {
private static final Logger LOG = LoggerFactory.getLogger(IptablesUtilsImpl.class);
@Autowired
DockerUtils dockerUtils;
@Override
public Map<String, List<ChainEntity>> showIptablesDetail(String containerId) {
/**
* Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
* 0 0 DROP all -- * * 10.1.100.3 0.0.0.0/0
*
* Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
*
* Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
* pkts bytes target prot opt in out source destination
*/
Map<String, List<ChainEntity>> map = new HashMap<>();
map.put("INPUT", new ArrayList<>());
map.put("FORWARD", new ArrayList<>());
map.put("OUTPUT", new ArrayList<>());
String result = dockerUtils.execInDocker(containerId, new String[]{"iptables", "-vnL"});
String[] lines = result.split("\n");
ChainEntity.Builder builder = ChainEntity.builder();
String key = "";
for (int i = 0; i < lines.length; i++) {
if(lines[i].startsWith("Chain INPUT")) {
builder = ChainEntity.builder().type(ChainType.INPUT);
key = "INPUT";
i++;
continue;
} else if(lines[i].startsWith("Chain FORWARD")) {
builder = ChainEntity.builder().type(ChainType.FORWARD);
key = "FORWARD";
i++;
continue;
} else if(lines[i].startsWith("Chain OUTPUT")) {
builder = ChainEntity.builder().type(ChainType.OUTPUT);
key = "OUTPUT";
i++;
continue;
}
if("".equals(lines[i])) {
continue;
}
String[] s = lines[i].replaceAll(" +", " ").trim().split(" ");
ChainEntity chain;
if(s.length == 9) {
chain = builder.pkts(Long.parseLong(s[0]))
.bytes(Long.parseLong(s[1]))
.target(s[2])
.prot(s[3])
.opt(s[4])
.in(s[5])
.out(s[6])
.source(s[7])
.destination(s[8])
.build();
map.get(key).add(chain);
}
}
return map;
}
/**
* 添加iptable项
* 这里应该还可以提供一个更加通用的模块,这里暂时先不实现
* example: iptables -I INPUT -s 172.0.0.2 -j DROP
* @param containerId
* @param kind
* @param chainType
* @param source
* @param destination
* @param policy
*/
@Override
public String addIptable(String containerId, String kind, ChainType chainType, String source, String destination, String policy) {
// 构建iptables的命令
String cmd = "iptables ";
switch (kind) {
case "insert":
cmd += "-I ";
break;
case "append":
cmd += "-A ";
break;
default:
throw new RuntimeException("不支持的操作");
}
cmd += chainType.toString() + " ";
if(!"".equals(source)) {
cmd += "-s " + source + " ";
}
if(!"".equals(destination)) {
cmd += "-d " + destination + " ";
}
if("".equals(policy)) {
throw new RuntimeException("policy不能为空");
}
// TODO: 差一步校验
cmd += "-j " + policy;
LOG.info("构建的cmd:[" + cmd + "]");
return dockerUtils.execInDocker(containerId, cmd.split(" "));
}
}
package top.ninwoo.utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import top.ninwoo.utils.config.DockerConfig;
import top.ninwoo.utils.entity.ChainEntity;
import top.ninwoo.utils.entity.ChainType;
import top.ninwoo.utils.entity.DockerContainer;
import top.ninwoo.utils.service.DockerService;
import top.ninwoo.utils.util.IptablesUtils;
import java.util.List;
import java.util.Map;
/**
* @Author joliu
* @Description
* @Date Create in 上午11:54 2019/10/29
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DockerConfig.class)
public class IptablesUtilsTests {
private static final Logger LOG = LoggerFactory.getLogger(IptablesUtilsTests.class);
@Autowired
IptablesUtils iptablesUtils;
@Autowired
DockerService dockerService;
private DockerContainer dockerContainer;
@Before
public void init() {
// 创建两个Docker
dockerContainer = new DockerContainer();
dockerContainer.setName("IptablesDocker");
dockerContainer.setImage("joliu/networktest");
dockerContainer.setCommand("sh");
dockerContainer = dockerService.runDocker(dockerContainer);
}
@Test
public void testAddIptables() {
testShowIptablesDetail();
iptablesUtils.addIptable(dockerContainer.getId(), "insert", ChainType.INPUT, "172.0.17.2", "", "DROP");
iptablesUtils.addIptable(dockerContainer.getId(), "insert", ChainType.OUTPUT, "172.0.17.2", "", "DROP");
iptablesUtils.addIptable(dockerContainer.getId(), "append", ChainType.INPUT, "172.0.17.3", "", "DROP");
testShowIptablesDetail();
}
public void testShowIptablesDetail() {
Map<String, List<ChainEntity>> iptablesList = iptablesUtils.showIptablesDetail(dockerContainer.getId());
iptablesList.forEach((k, v) -> {
System.out.println(k);
v.forEach(s -> {
System.out.println(s);
});
});
}
@After
public void close() {
dockerService.deleteDockerById(dockerContainer.getId());
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment