2024年最全zeek学习(五)—— 会话建立_zeek教程(1),2024年最新Golang零基础入门

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  1. 生成ConnTuple即key
  2. 查找key
  3. 找不到key,新建一个连接,并插入到管理器中
  4. 找到key,检测连接是否断开,断开重组并重新建立
bool IPBasedAnalyzer::AnalyzePacket(size_t len, const uint8\_t\* data, Packet\* pkt)
{
	// 建立key
	ConnTuple tuple;
	if ( ! BuildConnTuple(len, data, pkt, tuple) )
		return false;

	const std::shared_ptr<IP_Hdr>& ip_hdr = pkt->ip_hdr;
	detail::ConnKey key(tuple);

	Connection\* conn = session_mgr->FindConnection(key);

	if ( ! conn )
	{
		// 连接不存在,建立连接
		conn = NewConn(&tuple, key, pkt);
		// 插入到管理器中即添加到map中
		if ( conn )
			session_mgr->Insert(conn, false);
	}
	else
	{
		// 判断
		if ( conn->IsReuse(run_state::processing_start_time, ip_hdr->Payload()) )
		{
			conn->Event(connection_reused, nullptr);

			session_mgr->Remove(conn);
			conn = NewConn(&tuple, key, pkt);
			if ( conn )
				session_mgr->Insert(conn, false);
		}
		else
		{
			conn->CheckEncapsulation(pkt->encap);
		}
	}

	if ( ! conn )
		return false;

	// If we successfuly made a connection for this packet that means it'll eventually
	// get logged, which means we can mark this packet as having been processed.
	pkt->processed = true;

	bool is_orig = (tuple.src_addr == conn->OrigAddr()) && (tuple.src_port == conn->OrigPort());
	pkt->is_orig = is_orig;
	// IPV6的
	conn->CheckFlowLabel(is_orig, ip_hdr->FlowLabel());

	zeek::ValPtr pkt_hdr_val;
	// IPV6的
	if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 )
	{
		pkt_hdr_val = ip_hdr->ToPktHdrVal();
		conn->EnqueueEvent(ipv6_ext_headers, nullptr, conn->GetVal(), pkt_hdr_val);
	}
	// 事件回调
	if ( new_packet )
		conn->EnqueueEvent(new_packet, nullptr, conn->GetVal(),
		                   pkt_hdr_val ? std::move(pkt_hdr_val) : ip_hdr->ToPktHdrVal());

	conn->SetRecordPackets(true);
	conn->SetRecordContents(true);

	const u_char\* payload = pkt->ip_hdr->Payload();

	run_state::current_timestamp = run_state::processing_start_time;
	run_state::current_pkt = pkt;

	// TODO: Does this actually mean anything?
	if ( conn->GetSessionAdapter()->Skipping() )
		return true;
	// 分离到响应的子类处理
	DeliverPacket(conn, run_state::processing_start_time, is_orig, len, pkt);

	run_state::current_timestamp = 0;
	run_state::current_pkt = nullptr;


	// 重组包,不进行dump
	if ( pkt->ip_hdr->Reassembled() )
		pkt->dump_packet = false;
	else if ( conn->RecordPackets() )
	{
		pkt->dump_packet = true;

		// If we don't want the content, set the dump size to include just
		// the header.
		if ( ! conn->RecordContents() )
			pkt->dump_size = payload - pkt->data;
	}

	return true;
}

BuildConnTuple

UDP

bool UDPAnalyzer::BuildConnTuple(size_t len, const uint8\_t\* data, Packet\* packet, ConnTuple& tuple)
{
    uint32\_t min_hdr_len = sizeof(struct udphdr);
    if ( ! CheckHeaderTrunc(min_hdr_len, len, packet) )
        return false;
    
    tuple.src_addr = packet->ip_hdr->SrcAddr();
    tuple.dst_addr = packet->ip_hdr->DstAddr();
    
    const struct udphdr\* up = (const struct udphdr\*)packet->ip_hdr->Payload();
    tuple.src_port = up->uh_sport;
    tuple.dst_port = up->uh_dport;
    tuple.is_one_way = false;
    tuple.proto = TRANSPORT_UDP;
    
    return true;
	}

TCP

bool TCPAnalyzer::BuildConnTuple(size_t len, const uint8\_t\* data, Packet\* packet, ConnTuple& tuple)
{
    uint32\_t min_hdr_len = sizeof(struct tcphdr);
    if ( ! CheckHeaderTrunc(min_hdr_len, len, packet) )
        return false;
    
    tuple.src_addr = packet->ip_hdr->SrcAddr();
    tuple.dst_addr = packet->ip_hdr->DstAddr();
    
    data = packet->ip_hdr->Payload();
    
    const struct tcphdr\* tp = (const struct tcphdr\*)data;
    tuple.src_port = tp->th_sport;
    tuple.dst_port = tp->th_dport;
    tuple.is_one_way = false;
    tuple.proto = TRANSPORT_TCP;
    
    return true;
	}

FindConnection

using SessionMap = std::unordered_map<detail::Key, Session\*, detail::KeyHash>;

Connection\* Manager::FindConnection(const zeek::detail::ConnKey& conn_key)
{
	detail::Key key(&conn_key, sizeof(conn_key), detail::Key::CONNECTION_KEY_TYPE, false);

	auto it = session_map.find(key);
	if ( it != session_map.end() )
		return static\_cast<Connection\*>(it->second);

	return nullptr;
}

NewConn

zeek::Connection\* IPBasedAnalyzer::NewConn(const ConnTuple\* id, const detail::ConnKey& key,
                                           const Packet\* pkt)
{

	int src_h = ntohs(id->src_port);
	int dst_h = ntohs(id->dst_port);
	bool flip = false;
	// 检查是否需要分析此连接,并且检查是否反转服务器/客户端角色
	if ( ! WantConnection(src_h, dst_h, pkt->ip_hdr->Payload(), flip) )
		return nullptr;

	// 构造Connection对象
	Connection\* conn = new Connection(key, run_state::processing_start_time, id,
	                                  pkt->ip_hdr->FlowLabel(), pkt);
	// 设置传输层协议
	conn->SetTransport(transport);

	// 反转服务器/客户端角色
	if ( flip )
		conn->FlipRoles();
	// 构建协议分析器
	BuildSessionAnalyzerTree(conn);

	if ( new_connection )
		conn->Event(new_connection, nullptr);

	return conn;
}

BuildSessionAnalyzerTree
void IPBasedAnalyzer::BuildSessionAnalyzerTree(Connection\* conn)
{
	SessionAdapter\* root = MakeSessionAdapter(conn);
	analyzer::pia::PIA\* pia = MakePIA(conn);

	bool scheduled = analyzer_mgr->ApplyScheduledAnalyzers(conn, false, root);

	// Hmm... Do we want \*just\* the expected analyzer, or all
	// other potential analyzers as well? For now we only take
	// the scheduled ones.
	if ( ! scheduled )
	{ // Let's see if it's a port we know.
		if ( ! analyzers_by_port.empty() && ! zeek::detail::dpd_ignore_ports )
		{
			int resp_port = ntohs(conn->RespPort());
			std::set<zeek::Tag>\* ports = LookupPort(resp_port, false);

			if ( ports )
			{
				for ( const auto& port : \*ports )
				{
					analyzer::Analyzer\* analyzer = analyzer_mgr->InstantiateAnalyzer(port, conn);

					if ( ! analyzer )
						continue;

					root->AddChildAnalyzer(analyzer, false);
					DBG\_ANALYZER\_ARGS(conn, "activated %s analyzer due to port %d",
					                  analyzer_mgr->GetComponentName(port).c\_str(), resp_port);
				}
			}
		}
	}

	root->AddExtraAnalyzers(conn);

	if ( pia )
		root->AddChildAnalyzer(pia->AsAnalyzer());

	conn->SetSessionAdapter(root, pia);
	root->Init();
	root->InitChildren();

	PLUGIN\_HOOK\_VOID(HOOK_SETUP_ANALYZER_TREE, HookSetupAnalyzerTree(conn));
}


MakeSessionAdapter
SessionAdapter\* TCPAnalyzer::MakeSessionAdapter(Connection\* conn)
{
	auto\* root = new TCPSessionAdapter(conn);
	root->SetParent(this);

	conn->EnableStatusUpdateTimer();
	conn->SetInactivityTimeout(zeek::detail::udp_inactivity_timeout);

	return root;
}

ApplyScheduleAnalyzers
bool Manager::ApplyScheduledAnalyzers(Connection\* conn, bool init,
                                      packet_analysis::IP::SessionAdapter\* parent)
{
	if ( ! parent )
		parent = conn->GetSessionAdapter();

	if ( ! parent )
		return false;

	tag_set expected = GetScheduled(conn);

	for ( tag_set::iterator it = expected.begin(); it != expected.end(); ++it )
	{
		Analyzer\* analyzer = analyzer_mgr->InstantiateAnalyzer(\*it, conn);

		if ( ! analyzer )
			continue;

		parent->AddChildAnalyzer(analyzer, init);

		if ( scheduled_analyzer_applied )
			conn->EnqueueEvent(scheduled_analyzer_applied, nullptr, conn->GetVal(), it->AsVal());

		DBG\_ANALYZER\_ARGS(conn, "activated %s analyzer as scheduled",
		                  analyzer_mgr->GetComponentName(\*it).c\_str());
		}

	return expected.size();
	}

Insert

void Manager::Insert(Session\* s, bool remove_existing)
{
	Session\* old = nullptr;
	detail::Key key = s->SessionKey(true);

	if ( remove_existing )
	{
		auto it = session_map.find(key);
		if ( it != session_map.end() )
			old = it->second;

		session_map.erase(key);
	}

	InsertSession(std::move(key), s);

	if ( old && old != s )
	{
		// Some clean-ups similar to those in Remove() (but invisible
		// to the script layer).
		old->CancelTimers();
		old->SetInSessionTable(false);
		Unref(old);
	}
}

Connection

class Session : public Obj
{
public:

Session(double t, EventHandlerPtr timeout_event, EventHandlerPtr status_update_event = nullptr,
double status_update_interval = 0);

virtual ~Session() { }

/\*\*
\* Invoked when the session is about to be removed. Use Ref(this)
\* inside Done to keep the session object around, though it'll
\* no longer be accessible from the SessionManager.
\*/
virtual void Done() = 0;

/\*\*
\* Returns a key for the session. This is used as the key for storing
\* the session in SessionManager.
\*
\* @param copy Flag to indicate that the key returned must have a copy of the
\* key data instead of just a pointer to it.
\*/
virtual detail::Key SessionKey(bool copy) const = 0;

/\*\*
\* Set whether this session is in the session table.
\*/
void SetInSessionTable(bool in_table) { in_session_table = in_table; }

/\*\*
\* Return whether this session is in the session table.
\*/
bool IsInSessionTable() const { return in_session_table; }

double StartTime() const { return start_time; }
void SetStartTime(double t) { start_time = t; }
double LastTime() const { return last_time; }
void SetLastTime(double t) { last_time = t; }

// True if we should record subsequent packets (either headers or
// in their entirety, depending on record\_contents). We still
// record subsequent SYN/FIN/RST, regardless of how this is set.
bool RecordPackets() const { return record_packets; }
void SetRecordPackets(bool do_record) { record_packets = do_record ? 1 : 0; }

// True if we should record full packets for this session,
// false if we should just record headers.
bool RecordContents() const { return record_contents; }
void SetRecordContents(bool do_record) { record_contents = do_record ? 1 : 0; }

// Set whether to record \*current\* packet header/full.
void SetRecordCurrentPacket(bool do_record) { record_current_packet = do_record ? 1 : 0; }
void SetRecordCurrentContent(bool do_record) { record_current_content = do_record ? 1 : 0; }

/\*\*
\* Returns the associated "session" record.
\*/
virtual const RecordValPtr& GetVal() = 0;

[[deprecated("Remove in v5.1. Use GetVal().")]] const RecordValPtr& ConnVal()
{
return GetVal();
}

/\*\*
\* Return the memory allocation required by the session record. This requires at
\* least one call to Get() first in order to setup the record object.
\*/
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] virtual unsigned int
MemoryAllocationVal() const = 0;

[[deprecated("Remove in v5.1. Use MemoryAllocationVal().")]] unsigned int
MemoryAllocationConnVal() const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return MemoryAllocationVal();
#pragma GCC diagnostic pop
}

/\*\*
\* A lower-bound calculation of how much memory a session object is using.
\*/
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] virtual unsigned int
MemoryAllocation() const;

/\*\*
\* Generates session removal event(s). Must be overridden by child classes to
\* provide specific removal events.
\*/
virtual void RemovalEvent() = 0;

/\*\*
\* Generate an event for this session.
\*
\* @param f The handler for the event to be generated. If the handler doesn't
\* exist, this method doesn't generate anything.
\* @param analyzer
\* @param name If given, this will be passed as the first argument to the
\* handler, followed by the session value. If null, then the event's first
\* argument is the session value.
\*/
void Event(EventHandlerPtr f, analyzer::Analyzer\* analyzer = nullptr,
const char\* name = nullptr);

/\*\*
\* Enqueues an event associated with this session and given analyzer.
\*/
void EnqueueEvent(EventHandlerPtr f, analyzer::Analyzer\* analyzer, Args args);

/\*\*
\* A version of EnqueueEvent() taking a variable number of arguments.
\*/
template <class... Args>
std::enable_if_t<std::is_convertible_v<std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>>
EnqueueEvent(EventHandlerPtr h, analyzer::Analyzer\* analyzer, Args&&... args)
{
return EnqueueEvent(h, analyzer, zeek::Args{std::forward<Args>(args)...});
}

virtual void Describe(ODesc\* d) const override;

/\*\*
\* Sets the session to expire after a given amount of time.
\*
\* @param lifetime The amount of time in seconds from the current network time.
\*/
void SetLifetime(double lifetime);

/\*\*
\* Sets the inactivity timeout for this session.
\*
\* @param timeout The number of seconds of inactivity allowed for this session
\* before it times out.
\*/
void SetInactivityTimeout(double timeout);

/\*\*
\* Returns the inactivity timeout for the session.
\*/
double InactivityTimeout() const { return inactivity_timeout; }

/\*\*
\* Activates the timer for the status update event.
\*/
void EnableStatusUpdateTimer();

/\*\*
\* Cancels all timers associated with this session.
\*/
void CancelTimers();

/\*\*
\* Called when the lifetime of the session expires. Fires a timeout event and
\* removes the session from the manager.
\* TODO: This function has a terrible name considering there's an AddTimer() and
\* a RemoveTimer() method in this class as well.
\*
\* @param t This argument is ignored.
\*/
void DeleteTimer(double t);

/\*\*
\* Returns a string representation of the transport protocol referenced by the
\* session. This is used by SessionManager for statistics.
\*/
virtual std::string TransportIdentifier() const = 0;

AnalyzerConfirmationState AnalyzerState(const zeek::Tag& tag) const;
void SetAnalyzerState(const zeek::Tag& tag, AnalyzerConfirmationState);

protected:
friend class detail::Timer;

/\*\*
\* Add a given timer to expire at a specific time.
\*
\* @param timer A pointer to a method that will be called when the timer expires.
\* @param t The time when the timer expires. This is an absolute time, not a time
\* relative to the current network time.
\* @param do\_expire If set to true, the timer is also evaluated when Zeek
\* terminates.
\* @param type The type of timer being added.
\*/
void AddTimer(timer_func timer, double t, bool do_expire, zeek::detail::TimerType type);

/\*\*
\* Remove a specific timer from firing.
\*/
void RemoveTimer(zeek::detail::Timer\* t);



![img](https://img-blog.csdnimg.cn/img_convert/4fc44ba20758c198b2823f563361e71d.png)
![img](https://img-blog.csdnimg.cn/img_convert/8da1335e8f53856faa59dcbcffb5189b.png)
![img](https://img-blog.csdnimg.cn/img_convert/70e3ddd7bc611863bc8cb09c80d0332d.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

param type The type of timer being added.
\*/
void AddTimer(timer_func timer, double t, bool do_expire, zeek::detail::TimerType type);

/\*\*
\* Remove a specific timer from firing.
\*/
void RemoveTimer(zeek::detail::Timer\* t);



[外链图片转存中...(img-4cYi40y8-1715404582455)]
[外链图片转存中...(img-Wne4Hh98-1715404582456)]
[外链图片转存中...(img-Kxp3mUk2-1715404582456)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值