centos7的ntopng自定义

ntopng源码编译也是可以自定义一下的。
但是因为是c++的,不太好看。

总览

大致流程是

  • make uninstall
  • 修改源码
  • make
  • make install

分析源码,我觉得主要修改的函数是src/NetworkInterface.cpp中的dissectPacket函数,在注释那一段调用了processPacket处理数据包,因此可以在这里添加对于数据包的处理。

bool NetworkInterface::dissectPacket(const struct pcap_pkthdr *h,
				     const u_char *packet, bool *shaped,
				     u_int16_t *ndpiProtocol) {
	struct ndpi_ethhdr *ethernet, dummy_ethernet;
	u_int64_t time;
	static u_int64_t lasttime = 0;
	u_int16_t eth_type, ip_offset, vlan_id = 0, eth_offset = 0;
	u_int32_t null_type;
	int pcap_datalink_type = get_datalink();
	bool pass_verdict = true;
	......
    try {
		pass_verdict = processPacket(&h->ts, time, ethernet, vlan_id, iph,
				     ip6, h->caplen - ip_offset, h->len,
				     h, packet, shaped, ndpiProtocol);
		//*********************************** my code start ****************************************
		ntop->getTrace()->traceEvent(TRACE_NORMAL, "-------------------- normal -----------------------");
		//*********************************** my code end ****************************************
      } catch(std::bad_alloc& ba) {
		static bool oom_warning_sent = false;
		if(!oom_warning_sent) {
			ntop->getTrace()->traceEvent(TRACE_WARNING, "Not enough memory");
			oom_warning_sent = true;
		}
    }
    }
    break;
	......
	purgeIdle(last_pkt_rcvd);
	return(pass_verdict);
}

但是好像在processPacket函数里处理会更方便一点

bool NetworkInterface::processPacket(const struct bpf_timeval *when,
				     const u_int64_t time,
				     struct ndpi_ethhdr *eth,
				     u_int16_t vlan_id,
				     struct ndpi_iphdr *iph,
				     struct ndpi_ipv6hdr *ip6,
				     u_int16_t ipsize,
				     u_int16_t rawsize,
				     const struct pcap_pkthdr *h,
				     const u_char *packet,
				     bool *shaped,
				     u_int16_t *ndpiProtocol) {
	bool src2dst_direction;
	u_int8_t l4_proto;
	Flow *flow;
	u_int8_t *eth_src = eth->h_source, *eth_dst = eth->h_dest;
	IpAddress src_ip, dst_ip;
	u_int16_t src_port = 0, dst_port = 0, payload_len = 0;
	struct ndpi_tcphdr *tcph = NULL;
	struct ndpi_udphdr *udph = NULL;
	u_int16_t l4_packet_len;
	u_int8_t *l4, tcp_flags = 0, *payload = NULL;
	u_int8_t *ip;
	bool is_fragment = false, new_flow;
	bool pass_verdict = true;
	int a_shaper_id = DEFAULT_SHAPER_ID, b_shaper_id = DEFAULT_SHAPER_ID; /* Default */
	......
	//*********************************** my code start ****************************************
	ntop->getTrace()->traceEvent(TRACE_NORMAL, "");
	//*********************************** my code end ****************************************
	......    
    if(pass_verdict)
      incStats(when->tv_sec, iph ? ETHERTYPE_IP : ETHERTYPE_IPV6,
	       flow->get_detected_protocol().protocol,
	       rawsize, 1, 24 /* 8 Preamble + 4 CRC + 12 IFG */);

    bool dump_is_unknown = dump_unknown_traffic
      && (!flow->isDetectionCompleted() ||
	  flow->get_detected_protocol().protocol == NDPI_PROTOCOL_UNKNOWN);

    if(dump_is_unknown
       || dump_all_traffic
       || dump_security_packets
       || flow->dumpFlowTraffic()) {
      if(dump_to_disk) dumpPacketDisk(h, packet, dump_is_unknown ? UNKNOWN : GUI);
      if(dump_to_tap)  dumpPacketTap(h, packet, GUI);
    }

  } else
    incStats(when->tv_sec, iph ? ETHERTYPE_IP : ETHERTYPE_IPV6,
	     flow->get_detected_protocol().protocol,
	     rawsize, 1, 24 /* 8 Preamble + 4 CRC + 12 IFG */);

  return(pass_verdict);
}

细节

IpAddress Class

这里有结果结构体需要注意一下,比如现在的一个问题,是IpAddress这个类,这么定义的

struct ipAddress {
  u_int8_t ipVersion:3 /* Either 4 or 6 */, 
    localHost:1, privateIP:1, multicastIP:1, broadcastIP:1,
    notUsed:1 /* Future use */;

  union {
    struct ndpi_in6_addr ipv6;
    u_int32_t ipv4; /* Host byte code */
  } ipType;
};

/* **************************************** */

class IpAddress {
 private:
  struct ipAddress addr;
  u_int32_t ip_key;

  char* intoa(char* buf, u_short bufLen, u_int8_t bitmask);
  void checkIP();
  void compute_key();
  
 public:
  IpAddress();
  IpAddress(char *string);
  IpAddress(IpAddress *ip);
  IpAddress(u_int32_t _ipv4);
  IpAddress(struct ndpi_in6_addr *_ipv6);

  bool isEmpty();
  inline void reset()                                 { memset(&addr, 0, sizeof(addr));               }
  inline bool isIPv4()                                { return((addr.ipVersion == 4) ? true : false); }
  inline bool isIPv6()                                { return((addr.ipVersion == 6) ? true : false); }
  inline void set_ipv4(u_int32_t _ipv4)               { addr.ipVersion = 4, addr.ipType.ipv4 = _ipv4; compute_key(); }
  inline void set_ipv6(struct ndpi_in6_addr *_ipv6)   { addr.ipVersion = 6, memcpy(&addr.ipType.ipv6, _ipv6, sizeof(struct ndpi_in6_addr)); compute_key(); }
  inline u_int32_t get_ipv4()                         { return((addr.ipVersion == 4) ? addr.ipType.ipv4 : 0);     }
  inline struct ndpi_in6_addr* get_ipv6()             { return((addr.ipVersion == 6) ? &addr.ipType.ipv6 : NULL); }
  inline struct ipAddress* getIP()                    { return(&addr); };
  inline bool equal(u_int32_t ipv4_addr)              { if((addr.ipVersion == 4) && (addr.ipType.ipv4 == ipv4_addr)) return(true); else return(false); };
  inline bool equal(struct ndpi_in6_addr *ip6_addr)   { if((addr.ipVersion == 6) && (memcmp(&addr.ipType.ipv6, ip6_addr, sizeof(struct ndpi_in6_addr)) == 0)) return(true); else return(false); };
  inline bool equal(IpAddress *_ip)                   { return(this->compare(_ip) == 0); };

  void set_from_string(char *string);
  int compare(IpAddress *ip);
  inline u_int32_t key()                               { return(ip_key);         };
  void set(IpAddress *ip);
  inline bool isPrivateAddress()                       { return(addr.privateIP); };
  inline bool isMulticastAddress()                     { return(addr.multicastIP); };
  inline bool isBroadcastAddress()                     { return(addr.broadcastIP); };
  char* print(char *str, u_int str_len, u_int8_t bitmask = 0);
  bool isLocalHost(int16_t *network_id);
  bool isLocalInterfaceAddress();
  void deserialize(json_object *o);
  char* serialize();
  json_object* getJSONObject();
  bool match(patricia_tree_t *ptree);
  void* findAddress(patricia_tree_t *ptree);
};

这里主要看他的这个ipv4,是私有变量,所以得通过公共函数get_ipv4()调用。
然后可以看到这是一个u_int32_t类型的,它的返回值就是一个整型,如果想输出的话得用%d吧,我试了%d和%ld,一个好一个不好。
看下面的输出示例,后面的整型是%d前面的是%ld,前面就明显感觉怪怪的。

01/Dec/2020 15:48:33 [NetworkInterface.cpp:871] get a udp packet from br-ex Network from 139639896830578(176):13568 to 1744939200(0):56034
01/Dec/2020 15:48:33 [NetworkInterface.cpp:871] get a udp packet from br-ex Network from 139639896830578(176):13568 to 1744939200(0):56034
01/Dec/2020 15:48:33 [NetworkInterface.cpp:871] get a udp packet from br-ex Network from 139639896830578(176):13568 to 1744939200(0):61578
01/Dec/2020 15:48:33 [NetworkInterface.cpp:871] get a udp packet from br-ex Network from 16885952(176):4 to -1(255):35091
01/Dec/2020 15:48:34 [NetworkInterface.cpp:871] get a udp packet from br-ex Network from 139639721666752(0):20699 to 1920103026(176):13568
01/Dec/2020 15:48:34 [NetworkInterface.cpp:871] get a udp packet from eno16777736 Network from 139639721666752(0):31193 to 1920103026(176):13568

然后针对这个输出1920103026,试着把他转为IP地址。
先转为二进制1110010011100100111001001110010,但是发现只有31位,试着在前面补一个0,然后分段,就是01110010 01110010 01110010 01110010
再转为十进制114.114.114.114
这就是这个整型对应的IP地址了。

倒序

再试一下,1744939200,二进制为1101000000000011010100011000000,只有31位,也得补0。然后分段一下01101000 00000001 10101000 11000000,转为十进制是104.1.168.192
诶出现问题了,这个地址应该是192.168.1.104吧,所以说明这个东西他是反的,应该倒序一下。

参考链接

ntopng源码分析 - 丹西

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值