Knowing which event IDs to watch is half the job; getting them off every endpoint before the local Security log wraps is the other half. Windows Event Forwarding setup is the native, no-agent, no-cost way to implement event log forwarding — and it is what feeds nearly every SIEM-native Windows pipeline, including Microsoft Sentinel. This post is the build I run internally: source-initiated subscriptions, a Windows Server 2022 collector, and the Group Policy that wires the endpoints in.
Key Takeaways
- Source-initiated subscriptions scale better than collector-initiated for anything past a small lab — endpoints push to the collector instead of the collector pulling from each one.
- The Group Policy
SubscriptionManagerURL is what tells endpoints where to send events. - The forwarder runs locally on each source as NETWORK SERVICE, so it is NETWORK SERVICE — not the collector's computer account — that needs Event Log Readers membership to read the Security log.
- Custom event channels prevent the default ForwardedEvents log from overflowing on a busy collector — split by source type once you pass a few hundred endpoints.
- Forwarded events keep the original computer name in
Event/System/Computer; write queries against that field, not the collector hostname.
Environment
- Windows Server 2022 acting as the Windows Event Collector (WEC).
- Windows 10/11 and Windows Server 2019/2022 source machines, joined to the same Active Directory domain.
- WinRM available on TCP 5985 (HTTP) inside the management network. TCP 5986 (HTTPS) for sources crossing a less-trusted boundary.
- Group Policy management rights to push the subscription URL, the WinRM service state, and the Event Log Readers membership to source machines.
- PowerShell 5.1 or 7.4 on the collector for verification and ad-hoc queries.
The Problem
A busy domain controller will overwrite its Security log in hours, not days, regardless of the size you give it. 4624 and 4634 alone can generate thousands of events per minute. Trying to retain a week of DC security history on the DC itself is wishful thinking. Third-party log shippers solve this, but they bring agents, licensing, and a software supply chain that has to be vetted before it touches every server in the estate.
Windows Event Forwarding is built in, free, and rides on WinRM — which is already present on every supported Windows release. The trade-off is that the setup is fiddly, the documentation is scattered across several Microsoft Learn pages, and the failure modes are quiet. There are two modes: collector-initiated, where the collector pulls from a hand-listed set of sources, and source-initiated, where sources push to the collector based on Group Policy. Collector-initiated is fine for a handful of servers. Source-initiated is what scales, because new machines start forwarding the moment they apply the GPO and the collector does not have to know they exist beforehand.
The Solution
Step 1 — Prepare the Windows Event Collector
On the collector host, enable the Windows Event Collector service and configure WinRM. Two elevated commands handle both:
# Run elevated on the collector
wecutil qc /quiet
winrm quickconfig -quiet
wecutil qc sets the Wecsvc service to delayed auto-start, opens the firewall for WinRM, and registers the default WS-Management endpoint. After it completes, the Event Viewer → Subscriptions node becomes usable, and the ForwardedEvents log is ready to receive data.
Resize ForwardedEvents before any traffic arrives. The default 20 MB overflows within minutes once a few dozen domain controllers start pushing 4624s:
wevtutil sl ForwardedEvents /ms:8589934592 # 8 GB
Collector prep in one elevated session — wecutil qc, winrm quickconfig, and the ForwardedEvents resize.
Step 2 — Grant the forwarder permission to read the Security log
In a source-initiated subscription, nothing reads logs remotely. The forwarding plugin runs locally on each source as NETWORK SERVICE, reads the channels in the query, and pushes the events out. Most operational channels already grant read access to service accounts, but the Security log does not — its ACL covers SYSTEM, Administrators, and Event Log Readers only. So the account that needs the membership on every source is NT AUTHORITY\NETWORK SERVICE. The cleanest way to add it is a Group Policy Preferences entry targeting source machines:
Computer Configuration
→ Preferences
→ Control Panel Settings
→ Local Users and Groups
→ New → Local Group
Group: Event Log Readers (built-in)
Action: Update
Members: NT AUTHORITY\NETWORK SERVICE
Type the account name directly into the member field — the object picker will not find well-known principals when it is scoped to the domain. Keep the action on Update, which is additive; Replace would wipe whatever else is in the group. After the GPO applies, restart the WinRM service on the source (or reboot it): the service token is built at service start, so the new membership does nothing until then. On domain controllers, Event Log Readers is the domain Builtin group rather than a machine-local one, so a single entry covers all DCs.
An earlier version of this post said to add the collector's computer account here. That is the collector-initiated permission model, and in a source-initiated setup it grants nothing — I found out when a lab rebuild came up with a subscription that looked perfectly healthy and forwarded exactly one event. The symptoms are in Step 5.
Step 3 — Push the subscription URL via Group Policy
The single setting that activates source-initiated forwarding is the subscription manager URL. Under Computer Configuration → Administrative Templates → Windows Components → Event Forwarding → Configure target Subscription Manager, enable the policy and add the entry:
Server=http://wec01.example.local:5985/wsman/SubscriptionManager/WEC,Refresh=60
One GPO on the source OU carries both settings: the SubscriptionManager URL (Step 3) and the Event Log Readers membership (Step 2).
A few details that bite first-time deployments:
- The FQDN must resolve from every source. IP addresses technically work but break the Kerberos authentication WinRM expects by default.
Refresh=60tells the source to re-pull the subscription configuration every 60 seconds. Useful during rollout; raise it to 600 or higher once the fleet is stable.- WinRM also has to be running on the source. Set the Windows Remote Management (WS-Management) service startup to Automatic via a service GPO if it is not already.
After a gpupdate /force and a minute or two of patience, each source registers with the collector and appears under Event Viewer → Subscriptions → Source Computers. Microsoft's authoritative reference is on Microsoft Learn: Setting up a Source Initiated Subscription.
Step 4 — Author the event log forwarding subscription
Subscriptions can be created in the GUI, but XML is the only sane way to manage them at scale. Save the following as baseline.xml on the collector. It pulls the high-signal IDs from my Windows Event IDs reference and drops everything else:
<Subscription xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription">
<SubscriptionId>Baseline-Security</SubscriptionId>
<SubscriptionType>SourceInitiated</SubscriptionType>
<Description>Baseline forwarding: auth, account mgmt, process, PowerShell</Description>
<Enabled>true</Enabled>
<Uri>http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog</Uri>
<ConfigurationMode>Custom</ConfigurationMode>
<Delivery Mode="Push">
<Batching>
<MaxItems>20</MaxItems>
<MaxLatencyTime>30000</MaxLatencyTime>
</Batching>
<PushSettings>
<Heartbeat Interval="60000"/>
</PushSettings>
</Delivery>
<Query>
<![CDATA[
<QueryList>
<Query Id="0">
<Select Path="Security">
*[System[(EventID=1102 or EventID=4624 or EventID=4625 or EventID=4648 or
EventID=4672 or EventID=4688 or EventID=4720 or EventID=4724 or
EventID=4728 or EventID=4732 or EventID=4756 or EventID=4738 or
EventID=4698 or EventID=4699 or EventID=4702 or EventID=4719)]]
</Select>
<Select Path="Microsoft-Windows-PowerShell/Operational">
*[System[(EventID=4104)]]
</Select>
</Query>
</QueryList>
]]>
</Query>
<ReadExistingEvents>false</ReadExistingEvents>
<TransportName>http</TransportName>
<ContentFormat>RenderedText</ContentFormat>
<Locale Language="en-US"/>
<LogFile>ForwardedEvents</LogFile>
<AllowedSourceNonDomainComputers></AllowedSourceNonDomainComputers>
<AllowedSourceDomainComputers>O:NSG:NSD:(A;;GA;;;DC)(A;;GA;;;NS)</AllowedSourceDomainComputers>
</Subscription>
Register it with wecutil cs baseline.xml and confirm with wecutil es. The AllowedSourceDomainComputers SDDL above permits any domain controller (DC) plus NETWORK SERVICE (NS) — narrow it to a specific computer group SID for production. The XPath query is the same shape you would write in Event Viewer's filter dialog; copying a working filter and pasting it inside the Select element is a reliable starting point.
Step 5 — Verify and tune
The first thing to land in ForwardedEvents is usually a lone event ID 111 whose description reads "The file name is too long". That is the connection heartbeat each source writes when it registers with the collector, not an error — Event Viewer has no message resource for the Microsoft-Windows-EventForwarder provider, so it falls back to the Win32 error string for code 111. Real events should follow within the batching window. The source computer is in Event/System/Computer, not the collector's name — write queries against that field:
# Top forwarders in the last hour
Get-WinEvent -FilterHashtable @{
LogName = 'ForwardedEvents'
StartTime = (Get-Date).AddHours(-1)
} |
Group-Object MachineName |
Sort-Object Count -Descending |
Select-Object -First 20 Name, Count
The proof: 4624 logon events from DC1.lab.scriptographer landing in ForwardedEvents on the collector.
On the source, check the runtime status of the forwarding plugin:
# Inspect the subscription state from a source machine
wevtutil gl Microsoft-Windows-Forwarding/Operational
Get-WinEvent -LogName 'Microsoft-Windows-Forwarding/Operational' -MaxEvents 20
The two most common failures: WinRM not running on the source (event ID 102 in Microsoft-Windows-Forwarding/Operational), and NETWORK SERVICE missing from Event Log Readers — the tell for that one is "The subscription is created, but one or more channels in the query could not be read at this time" in the same log. Do not let a later "successfully connected to the subscription manager" message reassure you; that only confirms the collector is reachable, not that the forwarder can read what it is supposed to send. Both failures are GPO fixes, plus a WinRM restart on the source so the service token picks up the new group membership.
Step 6 — Split high-volume sources into custom event channels
Once you cross a few hundred endpoints, the default ForwardedEvents log churns fast enough that even an 8 GB log only holds a few hours of history. The fix is custom event channels: write a provider manifest, compile it with ecmangen, register it on the collector, and target separate subscriptions at separate logs — for example WEC-Auth, WEC-Process, and WEC-PowerShell. Each log gets its own size budget, retention policy, and query surface. Palantir's windows-event-forwarding repository on GitHub has production-grade manifests and subscription XMLs worth borrowing as a starting point.
Frequently Asked Questions
How do I implement event log forwarding on Windows?
To implement event log forwarding on a domain, use source-initiated Windows Event Forwarding: run wecutil qc and winrm quickconfig on the collector, add NT AUTHORITY\NETWORK SERVICE to Event Log Readers on the sources, push the SubscriptionManager URL via Group Policy, then register an XML subscription with wecutil cs. Endpoints start forwarding the moment they apply the GPO — no agent, no licensing, no cost beyond the collector itself.
Should I use HTTP or HTTPS for Windows Event Forwarding?
Inside an Active Directory domain, HTTP on TCP 5985 is already encrypted end-to-end by Kerberos and authenticated by the machine accounts on both sides. HTTPS on 5986 only adds value when sources are non-domain or cross an untrusted boundary, and that path also requires client certificates provisioned on every source. For a domain-joined fleet, HTTP is the documented default and the simpler operational choice.
Do I need a SIEM if I have Windows Event Forwarding?
Not strictly. A WEC collector with adequate log sizing and a few PowerShell queries handles ad-hoc incident response and small environments fine. A SIEM adds correlation across sources, longer retention, alerting, and search beyond just Windows logs. WEF is what feeds the SIEM in most native deployments — Microsoft Sentinel's Azure Monitor Agent, for example, can ingest forwarded events directly from a WEC.
Why are some events missing from forwarded logs even though they appear locally?
Three usual suspects: the event ID is not in the subscription's XPath query; the source has not yet refreshed the subscription configuration (wait for the Refresh interval to elapse); or NETWORK SERVICE on the source is not in Event Log Readers, so the forwarder cannot read the Security log. Run wecutil gr SUBSCRIPTION_NAME on the collector for the per-source heartbeat and last-error code, which usually points straight at the cause.
Why does ForwardedEvents show event ID 111 with "The file name is too long"?
Event 111 is the connection heartbeat a source writes when it registers with the collector — it means the subscription works, not that anything is wrong. Event Viewer has no message template for the Microsoft-Windows-EventForwarder provider, so it renders the raw Win32 error string for code 111 instead. If it stays the only event that ever arrives, the source cannot read the channels in the query; check the Event Log Readers membership from Step 2.
How big should the ForwardedEvents log be?
Budget at least 100 MB per active source per day at the baseline event set above. For a fleet of 500 endpoints, that is roughly a 50 GB log to retain a single day — which is the point at which custom event channels start paying for themselves. Domain controllers push significantly more volume than member servers, so split them out first.
Can I forward events from workgroup (non-domain) machines?
Yes, but with significantly more work. WinRM has to be configured with client certificates on the source, a matching certificate authority has to be trusted by the collector, and the source thumbprint has to be added to AllowedSourceNonDomainComputers in the subscription. For more than a handful of non-domain sources, an agent-based shipper is usually cheaper than maintaining the certificate plumbing.
Conclusion
Windows Event Forwarding is one of the more useful native Windows features that almost nobody enables until they have to. The setup is tedious — multiple GPOs, an XML subscription, an SDDL string — but everything is built in, costs nothing, and survives both the collector and the SIEM being swapped out for something else. Once it is running, the rest of the Windows-side detection stack quietly assumes it is there.
If I had to pick the single highest-leverage thing to do after configuring audit policy, this would be it. Centralised logs make every other monitoring decision — log retention, correlation rules, hunting queries — significantly easier.
Related Posts
- Essential Windows Event IDs for Security Monitoring — the events this subscription is designed to forward.
- PowerShell Quick Guide: Managing Event Log Sizes and Retention — the log sizing that has to come with WEF.
- From Logs to Threats: SIEM Correlation Rules for Real Attacks — what to build on top of a forwarded log feed.
Editorial note: posts on this blog are drafted with AI assistance and then reviewed, edited, and tested against a real environment before publishing. Commands, output, and screenshots come from systems I actually ran the work on.
0 comments:
Post a Comment