代码重构 防火墙 相关知识

54 篇文章 18 订阅

参考

  • 依据Linux命令
  • 以及sysconf下现有的iptables命令,详见hsm_sysconf_server/src/sysconf_server.cpp中的firewall规则。

接口名称

  • firewall_manager

目的(现实)

  • 根据网口直连获取当前eth0和eth1的各种信息
  • 保证设置的正确性      以及要针对管理口和服务口设计不同的初始化操作以及继承的恢复操作
  • 并且要把防火墙规则通过数据库存储

目的(虚拟)

  • 最终设计出封装性良好的接口与实现
  • 要经过详细的额外设计保证其通用性

开始

第一步

  • 首先需要学习以及尝试使用iptables命令控制防火墙

介绍

  • iptables 的主要功能是实现对网络数据包进出设备及转发的控制。当数据包需要进入设备、从设备中流出或者由该设备转发、路由时,都可以使用 iptables 进行控制
  • iptables 是集成在 Linux 内核中的包过滤防火墙系统。使用 iptables 可以添加、删除具体的过滤规则,iptables 默认维护着 4 个表和 5 个链,所有的防火墙策略规则都被分别写入这些表与链中。
  • “四表”是指 iptables 的功能,默认的 iptable s规则表有 filter 表(过滤规则表)、nat 表(地址转换规则表)、mangle(修改数据标记位规则表)、raw(跟踪数据表规则表)
    • filter 表:控制数据包是否允许进出及转发,可以控制的链路有 INPUT、FORWARD 和 OUTPUT。
    • nat 表:控制数据包中地址转换,可以控制的链路有 PREROUTING、INPUT、OUTPUT 和 POSTROUTING。
    • mangle:修改数据包中的原数据,可以控制的链路有 PREROUTING、INPUT、OUTPUT、FORWARD 和 POSTROUTING。
    • raw:控制 nat 表中连接追踪机制的启用状况,可以控制的链路有 PREROUTING、OUTPUT。
  • “五链”是指内核中控制网络的 NetFilter 定义的 5 个规则链。每个规则表中包含多个数据链:INPUT(入站数据过滤)、OUTPUT(出站数据过滤)、FORWARD(转发数据过滤)、PREROUTING(路由前过滤)和POSTROUTING(路由后过滤),防火墙规则需要写入到这些具体的数据链中。

2>/dev/null

iptables -c用法   

  • 这使管理员能够初始化规则的包和字节计数器(在INSERT,APPEND,REPLACE操作期间)

重启防火墙

2021年4月20日

今日存在的疑惑   2012年4月21日解决

execute_command干嘛的

#include "common/logging.h"

#include <cstdarg>
#include <cstdio>
#include <string>

namespace hsm {
namespace sys {

int execute_command(const std::string &command, std::string *output = nullptr,
                    bool redirect_stderr = false) {
  const auto &cmd = redirect_stderr ? command + " 2>&1" : command;
  auto pipe = popen(cmd.c_str(), "r");
  if (!pipe) {
    common::log_error("Can not exec command: {}", cmd);
    return -1;
  }
  // consume the output
  {
    char buffer[1024] = {0};
    while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
      if (output) {
        output->append(buffer);
      }
    }
  }
  return pclose(pipe);
}

} // namespace sys
} // namespace hsm
#include <string>
#include <cstdio>

int main(){
    FILE  *fp;
    char buffer[1024] = {0};
    fp = popen("cat /etc/passwd","r");
    fgets(buffer,sizeof(buffer),fp);
    printf("%s",buffer);
    pclose(fp);
}

fmt::format是否实现 字符串替换 {}  

iptables -C啥意思

  • -c, --set-counters PKTS BYTES
  • This enables the administrator to initialize the packet and byte counters of a rule (during INSERT, APPEND, REPLACE operations).
  • -c, --set-counters PKTS BYTES   这使管理员能够初始化一个规则的数据包和字节计数器(在INSERT、APPEND、REPLACE操作期间)。

{} 和 {1} 之间的区别

  • {} 将输入的参数进行替代
  • {1} 将输入的第一个参数进行替换

相关宏定义的声明

SYS_CONF_OK#define SYS_CONF_OK 0x0
SYS_CONF_SHELL_ERROR#define SYS_CONF_SHELL_ERROR 0x2
FIREWALL_CONF_FILE_PATH#define FIREWALL_CONF_FILE_PATH "/etc/firewall.conf"
FIREWALL_RULES_FILE_PATH#define FIREWALL_RULES_FILE_PATH "/etc/firewall.rules"
FIREWALL_INIT_SCRIPT#define FIREWALL_INIT_SCRIPT "/etc/init.d/11-firewall"
SYS_CONF_UNKNOWN_TYPE#define SYS_CONF_UNKNOWN_TYPE 0x4

std::unique_ptr<KeyValueConfStorage> firewall_config_storage;  KeyValueConfStorage结构

  •  storage.h 继承了类  SysconfStorage
#pragma once

#include "common/common.h"
#include "common/logging.h"

#include <mutex>
#include <string>

#include <json/json.h>

namespace hsm {
namespace sys {

class SysconfStorage {
public:
  explicit SysconfStorage(std::string persistence_file);

  virtual ~SysconfStorage() = default;

  virtual std::string serialize() = 0;

  bool sync(bool make_backup = true);

  void rollback();

protected:
  std::string storage_file;
  std::string backup_file;

  std::mutex sync_data_mutex;
};

class GlobalDataStorage : public SysconfStorage {
public:
  explicit GlobalDataStorage(std::string persistence_file);

  ~GlobalDataStorage() override { sync(); }

  std::string serialize() override;

  bool update_device_status(size_t device_status, bool sync_now = true);

  bool register_ukey(const std::string &ukey_info, bool sync_now = true);

  bool unregister_ukey(const std::string &ukey_info, bool sync_now = true);

  const json &get(const std::string &key) const;

  json &get(const std::string &key);

  const json &get() const { return data; }

private:
  json data;
};

class KeyValueConfStorage : public SysconfStorage {
public:
  explicit KeyValueConfStorage(std::string persistence_file);

  ~KeyValueConfStorage() override { sync(); }

  std::string serialize() override;

  bool set(const std::string &key, const std::string &value,
           bool sync_now = true);

  const std::string &get(const std::string &key);

  std::map<std::string, std::string> &get() { return data; }

private:
  std::map<std::string, std::string> data;
};

} // namespace sys
} // namespace hsm
  • storage.cpp 头文件中声明函数的定义
#include "storage.h"
#include "common/filesystem.h"
#include "common/string_utils.h"

#include <boost/filesystem.hpp>
#include <chrono>
#include <fstream>
#include <sstream>

namespace hsm {
namespace sys {

namespace fs = boost::filesystem;

size_t get_time_us() {
  using namespace std::chrono;
  return duration_cast<microseconds>(system_clock::now().time_since_epoch())
      .count();
}

SysconfStorage::SysconfStorage(std::string persistence_file)
    : storage_file(std::move(persistence_file)),
      backup_file(storage_file + "-") {}

bool SysconfStorage::sync(bool make_backup) {
  std::lock_guard<std::mutex> lock(sync_data_mutex);

  bool make_backup_ok = false;
  if (make_backup && fs::exists(storage_file)) {
    boost::system::error_code ec{};
    fs::rename(storage_file, backup_file, ec);
    if (ec) {
      common::log_error("Failed to sync, can not create backup file ({})",
                        backup_file);
      return false;
    }
    make_backup_ok = true;
  }
  auto content = serialize();
  std::ofstream f(storage_file);
  f << content;
  if (f.fail()) {
    common::log_error("Failed to sync, can not write data to storage file ({})",
                      storage_file);
    // revert storage file
    if (make_backup_ok) {
      boost::system::error_code ec{};
      fs::rename(backup_file, storage_file, ec);
      if (ec) {
        common::log_fatal(
            "Failed to sync, can not revert storage file ({}) from backup file "
            "({}), this is a unexpected fatal error",
            storage_file, backup_file);
      }
    }
    return false;
  }
  f.close();

  // sync filesystems
  if (common::file_sync(storage_file) && common::file_sync(backup_file)) {
    common::log_debug("Files are synchronized");
    return true;
  }

  return false;
}

void SysconfStorage::rollback() {
  boost::system::error_code ec{};
  fs::rename(backup_file, storage_file, ec);
  if (ec) {
    common::log_fatal("Can not revert storage file ({}) from backup file "
                      "({}), this is a unexpected fatal error",
                      storage_file, backup_file);
  }
}

GlobalDataStorage::GlobalDataStorage(std::string persistence_file)
    : SysconfStorage(std::move(persistence_file)) {
  {
    std::ifstream f(storage_file);
    if (f.is_open()) {
      std::stringstream ss;
      ss << f.rdbuf();
      data = json::parse(ss.str(), nullptr, false);
    }
  }
  if (!data.is_object()) {
    // try read backup file
    std::ifstream f(backup_file);
    if (f.is_open()) {
      std::stringstream ss;
      ss << f.rdbuf();
      data = json::parse(ss.str(), nullptr, false);
    }
    if (!data.is_object()) { // initialize an empty storage
      data = json();
      data["device_status"] = 0;
      data["ukey_list"] = json::object();
      sync();
    } else {
      sync(false);
    }
  }
  // simple check
  if (!data.contains("device_status") || !data.contains("ukey_list")) {
    common::log_fatal("Invalid sysconf storage content");
  }
}

std::string GlobalDataStorage::serialize() { return data.dump(); }

bool GlobalDataStorage::update_device_status(size_t device_status,
                                             bool sync_now) {
  data["device_status"] = device_status;

  IF_LIKELY(sync_now) { return sync(); }
  return true;
}

bool GlobalDataStorage::register_ukey(const std::string &ukey_info,
                                      bool sync_now) {
  json ukey_item;
  ukey_item["sn"] = ukey_info;
  ukey_item["time_us"] = get_time_us();
  data["ukey_list"][ukey_info] = std::move(ukey_item);

  IF_LIKELY(sync_now) { return sync(); }
  return true;
}

bool GlobalDataStorage::unregister_ukey(const std::string &ukey_info,
                                        bool sync_now) {
  data["ukey_list"].erase(ukey_info);

  IF_LIKELY(sync_now) { return sync(); }
  return true;
}

const json &GlobalDataStorage::get(const std::string &key) const {
  return data[key];
}

json &GlobalDataStorage::get(const std::string &key) { return data[key]; }

KeyValueConfStorage::KeyValueConfStorage(std::string persistence_file)
    : SysconfStorage(std::move(persistence_file)) {
  {
    std::ifstream f(storage_file);
    if (f.is_open()) {
      std::stringstream ss;
      ss << f.rdbuf();
      data = common::parse_config(ss.str());
    }
  }
  if (data.empty()) {
    // try read backup file
    std::ifstream f(backup_file);
    if (f.is_open()) {
      std::stringstream ss;
      ss << f.rdbuf();
      data = common::parse_config(ss.str());
    }
    // sync such valid backup data
    if (!data.empty()) {
      sync(false);
    }
  }
}

std::string KeyValueConfStorage::serialize() {
  if (data.empty()) {
    data["this_is_an_empty_config"] = "";
  }
  std::ostringstream ss;
  for (const auto &item : data) {
    ss << item.first << "=" << item.second << std::endl;
  }
  return ss.str();
}

bool KeyValueConfStorage::set(const std::string &key, const std::string &value,
                              bool sync_now) {
  data[key] = value;

  IF_LIKELY(sync_now) { return sync(); }
  return true;
}

const std::string &KeyValueConfStorage::get(const std::string &key) {
  return data[key];
}

} // namespace sys
} // namespace hsm

获取eth0和eth1的各种信息

任务

  • 梳理逻辑,画uml图

通用模型设计(补充)

  •  限制每个客户端最大并发数不超过3个(xshell终端)
  • iptables –A INPUT –p tcp --dport 22 –s 192.168.1.0/24 –m connlimt –connlimit-above 2 –j DROP
  • 限制速度(-m limit --limit匹配速率| --burst缓冲数量)
  • iptables –A INPUT –d 192.168.1.63 –m limit --limit 5/s --burst 100–j ACCEPT(在100个包内不限速,超过一百个包限制每秒只传5个包)
  • 查看当前的iptables的状态
  • 1,iptables -nL #默认查看filter表的状态,如果需要查看其他表的状态加上 -t 表名
  • 2,iptables -nL --line-numbers #可以列出序列号,数据的插入和删除和查看
  • 3,iptables -nL --line-numbers --verbose #可以查看到包过滤的流量统计,访问次数等
  • 还原配置
  • iptables-restore < /etc/sysconfig/iptables 
  • 限制单个IP一分钟内建立的连接数
  • iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 25 -j REJECT
  • 拒绝所有访问
  • iptables -A INPUT -j DROP #这个一般放到最后,不然会对前面的规则造成影响
  • 针对端口开放(需要指明协议)
  • iptables -I INPUT -p tcp --dport 22 -j ACCEPT
  • 针对协议开放
  • iptables -I INPUT -p imcp -j ACCEPT
  • 根据时段限制访问
  • iptables -A INPUT -p tcp -m time --timestart 00:00 --timestop 02:00 -j DROP #这里的时间是指UTC时间记得换算

2021年4月22日

注意事项

1,数据库存储 防火墙的规则,将先前的命令进行细分

iptables -A INPUT -p tcp -s 10.159.1.0/24 --dport 22 -j ACCEPT
  • 比如上述命令,字段细分 INPUT、目标设备(eth0/eth1)、端口 、跳转行为(-j) 、ACCEPT等

2,同理  也将上述字段 作为 函数的一个输入参数 

2021年4月23号

  • iptables -F #清除所有制定的规则
  • iptables -X#清除用户自定义的chain
  • iptables -Z#将所有流量统计归0
  • 但是并非执行后就万事大吉了。你仍然需要检查规则是不是真的清空了,因为有的linux发行版上这个命令不会清除NAT表中的规则,此时只能手动清除:iptables -t NAT -F
  • iptables工作原理及iptables命令行使用介绍
  • 只允许 mac地址为aa:bb:cc:dd:ee:ff 的机器访问本地ssh端口   iptables -A INPUT -m mac --mac-source aa:bb:cc:dd:ee:ff -p tcp --dport 22 -j ACCEPT

  

linux查看网卡的部分具体命令

  • /sbin/ifconfig | grep ether   ether是使用ifconfig查看到的网口信息,有些Linux发行版本的MAC地址字段为HWaddr,有些Linux发行版本的MAC地址字段为ether。根据实际情况选择上面命令
  • 如果想只提取网卡MAC地址,可以使用下面命令(用具体的网卡名替换xxx)      ifconfig xxx | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'

  •  cat /sys/class/net/xxx/address查看
  • dmesg | grep eth

 

和MAC有关的相关命令

  • 1、阻止MAC地址为XX:XX:XX:XX:XX:XX主机的所有通信:   iptables -A INPUT -m mac --mac-source XX:XX:XX:XX:XX:XX -j DROP
  • 2、允许MAC地址为XX:XX:XX:XX:XX:XX主机访问22端口:   iptables -A INPUT -p tcp --destination-port 22 -m mac --mac-source XX:XX:XX:XX:XX:XX -j ACCEPT

参考链接

配置参考

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值