{"id":18952422,"url":"https://github.com/tailscale/wintun","last_synced_at":"2025-04-16T01:33:56.490Z","repository":{"id":103376222,"uuid":"183955981","full_name":"tailscale/wintun","owner":"tailscale","description":"Fork of https://git.zx2c4.com/wintun","archived":false,"fork":false,"pushed_at":"2023-10-28T08:53:41.000Z","size":314,"stargazers_count":13,"open_issues_count":0,"forks_count":8,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-11T16:18:54.163Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tailscale.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-28T20:33:08.000Z","updated_at":"2024-12-28T13:18:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"ab3caf5c-110c-48e8-8aed-e209bd48fba3","html_url":"https://github.com/tailscale/wintun","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tailscale%2Fwintun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tailscale%2Fwintun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tailscale%2Fwintun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tailscale%2Fwintun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tailscale","download_url":"https://codeload.github.com/tailscale/wintun/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249182564,"owners_count":21226090,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T13:33:22.150Z","updated_at":"2025-04-16T01:33:56.484Z","avatar_url":"https://github.com/tailscale.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [Wintun Network Adapter](https://www.wintun.net/)\n### TUN Device Driver for Windows\n\nThis is a layer 3 TUN driver for Windows 7, 8, 8.1, and 10. Originally created for [WireGuard](https://www.wireguard.com/), it is intended to be useful to a wide variety of projects that require layer 3 tunneling devices with implementations primarily in userspace.\n\n## Installation\n\nThe following snippet may be used inside of a WiX `\u003cProduct\u003e` element for including Wintun inside of a Windows Installer. Note that **MSI is the only supported method of installing Wintun**; if you're using a different install system (such as NSIS) and cannot bother to switch to MSI/WiX, then simply bundle an embedded MSI that you can execute with `msiexec.exe`.\n\n```xml\n\u003cDirectoryRef Id=\"INSTALLFOLDER\"\u003e\n    \u003cMerge Id=\"WintunMergeModule\" Language=\"0\" DiskId=\"1\" SourceFile=\"path\\to\\wintun-x.y-amd64.msm\" /\u003e\n\u003c/DirectoryRef\u003e\n\u003cFeature Id=\"WintunFeature\" Title=\"Wintun\" Level=\"1\"\u003e\n    \u003cMergeRef Id=\"WintunMergeModule\" /\u003e\n\u003c/Feature\u003e\n```\n\nIt is advisable to use the prebuilt and Microsoft-signed MSM files from [Wintun.net](https://www.wintun.net/).\n\n## Usage\n\nAfter loading the driver and creating a network interface the typical way using [SetupAPI](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi), open the NDIS device object associated with the PnPInstanceId, enabling all forms of file sharing:\n\n```C\nTCHAR *InterfaceList = NULL;\nfor (;;) {\n    free(InterfaceList);\n    DWORD RequiredBytes;\n    if (CM_Get_Device_Interface_List_Size(\u0026RequiredBytes, (LPGUID)\u0026GUID_DEVINTERFACE_NET,\n        InstanceId, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)\n        return FALSE;\n    InterfaceList = calloc(sizeof(*InterfaceList), RequiredBytes);\n    if (!InterfaceList)\n        return FALSE;\n    CONFIGRET Ret = CM_Get_Device_Interface_List((LPGUID)\u0026GUID_DEVINTERFACE_NET, InstanceId,\n                    InterfaceList, RequiredBytes, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);\n    if (Ret == CR_SUCCESS)\n        break;\n    if (Ret != CR_BUFFER_SMALL) {\n        free(InterfaceList);\n        return FALSE;\n    }\n}\nHANDLE WintunHandle = CreateFile(InterfaceList, GENERIC_READ | GENERIC_WRITE,\n                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\n                                 NULL, OPEN_EXISTING, 0, NULL);\nfree(InterfaceList);\n...\n```\n\n### Ring layout\n\nYou must allocate two ring structs, one for receiving and one for sending:\n\n```C\ntypedef struct _TUN_RING {\n    volatile ULONG Head;\n    volatile ULONG Tail;\n    volatile LONG Alertable;\n    UCHAR Data[];\n} TUN_RING;\n```\n\n- `Head`: Byte offset of the first packet in the ring. Its value must be a multiple of 4 and less than ring capacity.\n\n- `Tail`: Byte offset of the start of free space in the ring. Its value must be multiple of 4 and less than ring capacity.\n\n- `Alertable`: Zero when the consumer is processing packets, non-zero when the consumer has processed all packets and is waiting for `TailMoved` event.\n\n- `Data`: The ring data.\n\nIn order to determine the size of the `Data` array:\n\n1. Pick a ring capacity ranging from 128kiB to 64MiB bytes. This capacity must be a power of two (e.g. 1MiB). The ring can hold up to this much data.\n2. Add 0x10000 trailing bytes to the capacity, in order to allow for always-contigious packet segments.\n\nThe total ring size memory is then `sizeof(TUN_RING) + capacity + 0x10000`.\n\nEach packet is stored in the ring aligned to `sizeof(ULONG)` as:\n\n```C\ntypedef struct _TUN_PACKET {\n    ULONG Size;\n    UCHAR Data[];\n} TUN_PACKET;\n```\n\n- `Size`: Size of packet (max 0xFFFF).\n\n- `Data`: Layer 3 IPv4 or IPv6 packet.\n\n### Registering rings\n\nIn order to register the two `TUN_RING`s, prepare a registration struct as:\n\n```C\ntypedef struct _TUN_REGISTER_RINGS {\n    struct {\n        ULONG RingSize;\n        TUN_RING *Ring;\n        HANDLE TailMoved;\n    } Send, Receive;\n} TUN_REGISTER_RINGS;\n```\n\n- `Send.RingSize`, `Receive.RingSize`: Sizes of the rings (`sizeof(TUN_RING) + capacity + 0x10000`, as above).\n\n- `Send.Ring`, `Receive.Ring`: Pointers to the rings.\n\n- `Send.TailMoved`: A handle to an [`auto-reset event`](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventa) created by the client that Wintun signals after it moves the `Tail` member of the send ring.\n\n- `Receive.TailMoved`: A handle to an [`auto-reset event`](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventa) created by the client that the client will signal when it changes `Receive.Ring-\u003eTail` and `Receive.Ring-\u003eAlertable` is non-zero.\n\nWith events created, send and receive rings allocated, and registration struct populated, [`DeviceIoControl`](https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol)(`TUN_IOCTL_REGISTER_RINGS`: 0xca6ce5c0) with pointer and size of descriptor struct specified as `lpInBuffer` and `nInBufferSize` parameters. You may call `TUN_IOCTL_REGISTER_RINGS` on one handle only.\n\n\n### Writing to and from rings\n\nReading packets from the send ring may be done as:\n\n```C\nfor (;;) {\n    TUN_PACKET *Next = PopFromRing(Rings-\u003eSend.Ring);\n    if (!Next) {\n        Rings-\u003eSend.Ring-\u003eAlertable = TRUE;\n        Next = PopFromRing(Rings-\u003eSend.Ring);\n        if (!Next) {\n            WaitForSingleObject(Rings-\u003eSend.TailMoved, INFINITE);\n            Rings-\u003eSend.Ring-\u003eAlertable = FALSE;\n            continue;\n        }\n        Rings-\u003eSend.Ring-\u003eAlertable = FALSE;\n        ResetEvent(Rings-\u003eSend.TailMoved);\n    }\n    SendToClientProgram(Next);\n}\n```\n\nIt may be desirable to spin for some time under heavy use before waiting on the `TailMoved` event, in order to reduce latency.\n\nWhen closing the handle, Wintun will set the `Tail` to 0xFFFFFFFF and set the `TailMoved` event to unblock the waiting user process.\n\nWriting packets to the receive ring may be done as:\n\n```C\nfor (;;) {\n    TUN_PACKET *Next = ReceiveFromClientProgram();\n    WriteToRing(Rings-\u003eReceive.Ring, Next);\n    if (Rings-\u003eReceive.Ring-\u003eAlertable)\n        SetEvent(Rings-\u003eRecieve.TailMoved);\n}\n```\n\nWintun will abort reading the receive ring on invalid `Head` or `Tail` or on a bogus packet. In this case, Wintun will set the `Head` to 0xFFFFFFFF. In order to restart it, reopen the handle and call `TUN_IOCTL_REGISTER_RINGS` again. However, it should be entirely possible to avoid feeding Wintun bogus packets and invalid offsets.\n\n## Building\n\n**Do not distribute drivers named \"Wintun\", as they will most certainly clash with official deployments. Instead distribute [the signed MSMs from Wintun.net](https://www.wintun.net/).** If you are unable to use MSMs, [consult the MSI creation instructions](msi-example/README.md).\n\nGeneral requirements:\n\n- [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/)\n- [Windows Driver Kit for Windows 10, version 1903](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)\n\n`wintun.sln` may be opened in Visual Studio for development and building. Be sure to run `bcdedit /set testsigning on` before to enable unsigned driver loading. The default run sequence (F5) in Visual Studio will build and insert Wintun.\n\n## License\n\nThe entire contents of this repository, including all documentation code, is \"Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.\" and is licensed under the [GPLv2](COPYING).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftailscale%2Fwintun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftailscale%2Fwintun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftailscale%2Fwintun/lists"}