{"id":50654414,"url":"https://github.com/geiserx/tailscale-rs","last_synced_at":"2026-06-14T10:00:44.072Z","repository":{"id":363201971,"uuid":"1262326977","full_name":"GeiserX/tailscale-rs","owner":"GeiserX","description":"A best-effort, pure-Rust port of Tailscale's Go tsnet — embed a Tailscale node directly in your Rust app. Fork of tailscale/tailscale-rs.","archived":false,"fork":false,"pushed_at":"2026-06-13T06:29:56.000Z","size":7383,"stargazers_count":2,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-13T09:26:53.495Z","etag":null,"topics":["async","derp","ffi","magicdns","mesh-networking","mesh-vpn","nat-traversal","networking","noise-protocol","overlay-network","rust","tailscale","tokio","tsnet","userspace-networking","vpn","vpn-client","wireguard","wireguard-rust","zero-trust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/GeiserX.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"geiserx","patreon":"geiser","buy_me_a_coffee":"geiser","thanks_dev":"u/gh/geiserx"}},"created_at":"2026-06-07T21:29:49.000Z","updated_at":"2026-06-13T05:39:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/GeiserX/tailscale-rs","commit_stats":null,"previous_names":["geiserx/tailscale-rs"],"tags_count":64,"template":false,"template_full_name":null,"purl":"pkg:github/GeiserX/tailscale-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Ftailscale-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Ftailscale-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Ftailscale-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Ftailscale-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GeiserX","download_url":"https://codeload.github.com/GeiserX/tailscale-rs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeiserX%2Ftailscale-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34316823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["async","derp","ffi","magicdns","mesh-networking","mesh-vpn","nat-traversal","networking","noise-protocol","overlay-network","rust","tailscale","tokio","tsnet","userspace-networking","vpn","vpn-client","wireguard","wireguard-rust","zero-trust"],"created_at":"2026-06-07T23:01:31.574Z","updated_at":"2026-06-14T10:00:44.039Z","avatar_url":"https://github.com/GeiserX.png","language":"Rust","funding_links":["https://github.com/sponsors/geiserx","https://patreon.com/geiser","https://buymeacoffee.com/geiser","https://thanks.dev/u/gh/geiserx"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/banner.svg\" alt=\"tailscale-rs\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003etailscale-rs\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/GeiserX/tailscale-rs/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/GeiserX/tailscale-rs/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-BSD--3--Clause-blue.svg\" alt=\"License: BSD-3-Clause\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/MSRV-1.94.1-orange.svg\" alt=\"MSRV 1.94.1\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/edition-2024-blue.svg\" alt=\"Rust edition 2024\"\u003e\n  \u003ca href=\"https://github.com/tailscale/tailscale-rs\"\u003e\u003cimg src=\"https://img.shields.io/badge/fork%20of-tailscale%2Ftailscale--rs-purple\" alt=\"fork of tailscale/tailscale-rs\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nA fork of [tailscale/tailscale-rs](https://github.com/tailscale/tailscale-rs).\n\n`tailscale-rs` is a work-in-progress Tailscale library written in Rust, with language bindings to\nC, Elixir, and Python.\n\n\u003e [!NOTE]\n\u003e This project is **not associated with Tailscale Inc.** — it is an independent, unofficial fork.\n\u003e See [Legal](#legal).\n\n\u003e [!CAUTION]\n\u003e This software is unstable and insecure.\n\u003e\n\u003e I welcome enthusiasm and interest, but please **do not** build production software using these\n\u003e libraries or rely on it for data privacy until I've had a chance to batten down some hatches\n\u003e and complete a third-party audit.\n\u003e\n\u003e See [Caveats](#caveats) for more details.\n\n## Getting Started\n\nThe following instructions are for Rust! For other languages, see the language-specific README:\n- [C](ts_ffi/README.md)\n- [Elixir](ts_elixir/README.md)\n- [Python](ts_python/README.md) \n\nAdd this dependency line to your `Cargo.toml`:\n\n```toml\n[dependencies]\n# Published as `geiserx_tailscale`; imported as `tailscale`.\ntailscale = { package = \"geiserx_tailscale\", version = \"0.6\" }\n```\n\n\u003e Or depend on the latest from git:\n\u003e\n\u003e ```toml\n\u003e [dependencies]\n\u003e tailscale = { package = \"geiserx_tailscale\", git = \"https://github.com/GeiserX/tailscale-rs\" }\n\u003e ```\n\nEither way, you import it as `tailscale` (e.g. `use tailscale::Device;`) — the crate name on\ncrates.io is `geiserx_tailscale`, but the library name is `tailscale`.\n\nExamples of using the `tailscale` crate can be found in [`examples/`](examples/README.md).\n\nFor instructions on how to run tests, lints, etc., see [CONTRIBUTING.md](CONTRIBUTING.md). For the high-level architecture and\nrepository layout, see [ARCHITECTURE.md](ARCHITECTURE.md).\n\n### Code sample\n\nA simple UDP client that periodically sends messages to a tailnet peer at `100.64.0.1:5678`:\n\n```rust\nuse std::{\n    time::Duration,\n    net::Ipv4Addr,\n    error::Error,\n};\nuse tailscale::{Config, Device};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n    // Open a new connection to tailscale\n    let dev = Device::new(\n        \u0026Config::default_with_key_file(\"tsrs_keys.json\").await?,\n        Some(\"YOUR_AUTH_KEY_HERE\".to_owned()),\n    ).await?;\n\n    // Bind a UDP socket on this node's tailnet IP, port 1234\n    let sock = dev.udp_bind((dev.ipv4().await?, 1234).into()).await?;\n\n    // Send a packet containing \"ping\" to 100.64.0.1:5678 once per second\n    loop {\n        sock.send_to((Ipv4Addr::new(100, 64, 0, 1), 5678).into(), b\"ping\").await?;\n        tokio::time::sleep(Duration::from_secs(1)).await;\n    }\n}\n```\n\n## How it works\n\nA `Device` joins the tailnet by authenticating to the **control plane** over Tailscale's\nTS2021 (Noise) channel, then moves data over an in-process **WireGuard** data plane — connecting\npeer-to-peer where NAT traversal allows, and relaying through **DERP** otherwise.\n\n```mermaid\nflowchart LR\n    App[\"Your app\u003cbr/\u003e(Rust / C / Elixir / Python)\"] --\u003e Device[\"tailscale::Device\"]\n    Device --\u003e|\"TS2021 / Noise\"| Control[\"Control plane\u003cbr/\u003e(login, MapResponse)\"]\n    Device --\u003e WG[\"WireGuard data plane\u003cbr/\u003e(userspace netstack)\"]\n    WG --\u003e|\"direct (STUN + Disco)\"| Peer[\"Tailnet peer\"]\n    WG -.-\u003e|\"fallback relay\"| DERP[\"DERP relay\"]\n    DERP -.-\u003e Peer\n```\n\nFor the full module layout and design notes, see [ARCHITECTURE.md](ARCHITECTURE.md).\n\n## Caveats\n\nThis software is still a work-in-progress! I'm providing it in the open at this stage out of a\nbelief in open-source and to see where the community runs with it, but please be aware of a few\nimportant considerations:\n\n- This implementation contains unaudited cryptography and hasn't undergone a comprehensive security\n  analysis. Conservatively, assume there could be a critical security hole meaning anything you send\n  or receive could be in the clear on the public Internet.\n- There are no compatibility guarantees at the moment. This is early-days software \u0026mdash; I may\n  break dependent code in order to get things right.\n- Direct peer-to-peer connections via NAT traversal are implemented (STUN-discovered endpoints and\n  Disco, with `CallMeMaybe` hole-punching over DERP), and traffic falls back to DERP relays when no\n  direct path is available. Symmetric-NAT birthday-paradox hole-punching is not yet implemented,\n  so behind some NATs a flow stays relayed through DERP, which caps its throughput.\n- The `TS_RS_EXPERIMENT` environment variable is required to be set to `this_is_unstable_software`\n  for all code linked against `tailscale-rs`; this includes Rust, C, Elixir, and Python code. I'll\n  remove this requirement after a third-party code/cryptography audit and any necessary fixes.\n\nFor the full security posture — unaudited cryptography, the Tailnet Lock enforcement gap, peerAPI\ncapability limitations, at-rest key handling, and how to report a vulnerability — see\n[SECURITY.md](SECURITY.md).\n\n## Versioning, Releases, and Compatability\n\nI follow semver and aim to make a point release roughly monthly. Since this is pre-1.0, there are no\nbackwards-compatability guarantees. I'm aiming for a stable 1.0 release as soon as I can, but there's\ncurrently no timeline.\n\n## MSRV and Edition\n\nThe current MSRV is 1.94.1. The current edition is Rust 2024.\n\n`tailscale-rs` has a rolling MSRV (Minimum Supported Rust Version) policy to support the current\nand previous Rust compiler versions, and the latest\n[edition of Rust](https://doc.rust-lang.org/edition-guide/editions/index.html).\n\nI may lag the latest version/edition in rare cases to let dependencies catch up and to\nperform any necessary fixes.\n\n## Platform Support\n\nThe following platforms and architectures are supported:\n\n- Linux (`x86_64`/`ARM64`)\n- macOS (`ARM64`)\n- Windows (`x86_64`)\n\n## Status\n\n`tailscale-rs` is a work-in-progress - I'm still rapidly iterating, fixing bugs, and adding new\nfeatures. I aim to keep this section up-to-date, but the [issue tracker](https://github.com/GeiserX/tailscale-rs/issues)\nis the best way to see the latest updates.\n\n### Implemented\n\nThese are features that are currently implemented:\n\n- Basics\n  - Create TCP and UDP sockets on the tailnet\n  - Direct connections via NAT traversal (STUN-discovered endpoints and Disco, with `CallMeMaybe`\n    hole-punching over DERP); traffic falls back to public DERP relays only when no direct path is\n    available\n  - Peer lookups (addressing peers by MagicDNS name, in-process)\n  - MagicDNS (an in-netstack resolver on `100.100.100.100:53` answering A/AAAA/PTR for tailnet\n    peers and control-pushed static records (`ExtraRecords`); by default fail-closed — with no\n    `fallback_resolvers` configured, non-tailnet names get NXDOMAIN and are never forwarded\n    upstream. Configuring `fallback_resolvers` opts in to forwarding non-tailnet query names to\n    those upstream resolvers.)\n  - Split DNS (per-domain `routes` from control: a query matching a route's suffix is forwarded to\n    that route's resolvers by longest-suffix match; a route with an empty resolver list is a\n    negative route answering NXDOMAIN. Recursive forwarding to `fallback_resolvers`/`resolvers`\n    applies only when no route matches.)\n  - Using a subnet router (accepting peer-advertised subnet routes via `accept_routes`; opt-in,\n    fail-closed off by default)\n  - Using an exit node (routing internet-bound traffic through a chosen peer via `exit_node`,\n    selectable by Tailscale stable ID, tailnet IP, or MagicDNS name; opt-in, fail-closed off by\n    default). The exit node can also be changed at runtime with `Device::set_exit_node` — the\n    equivalent of Go `tsnet`'s `LocalClient.EditPrefs(ExitNodeID/ExitNodeIP)` — without recreating\n    the device.\n  - Recursive MagicDNS forwarding in TUN mode (the `100.100.100.100:53` resolver now forwards\n    non-tailnet names recursively in TUN mode, matching the netstack-mode behavior; the same\n    fail-closed default applies — without `fallback_resolvers`, non-tailnet names get NXDOMAIN)\n  - Tailscale Serve: `Proxy`, `Text`, `TcpForward`, plus HTTP `Path` (path-prefix mux) and\n    `Redirect` (HTTP 3xx) handlers; all TLS-terminating targets are validated and dispatched\n    fail-closed (unmatched path → 404, backend dial failure → drop)\n  - Tailnet Lock (TKA), **partial**: per-peer node-key signature verification is wired and\n    unit-tested at the peer-trust chokepoint and fails closed when a trusted-key `Authority` is\n    supplied. Live enforcement is **currently inert** — the AUM-chain sync RPC that would supply the\n    `Authority` is not yet implemented, so a compromised control plane can still inject peer keys.\n    See [SECURITY.md](SECURITY.md) before relying on it.\n  - Communicate with the Tailscale Go client, `tsnet`, and `libtailscale`\n- Language support\n  - Rust API\n  - C, Elixir, and Python bindings\n\n### Coming Soon\n\nThese are features or efforts I have in the pipeline and am actively working towards, but with\nno guarantees on timeline or completion:\n\n- Third-party code and cryptography audit\n\n### Unsupported\n\nThis is an incomplete list of features in the Tailscale Go client, `tsnet`, and/or `libtailscale`\nthat are *not* currently supported. I'd like to add all of these eventually! If there's something\non this list you'd like to see supported, or something _not_ on this list you're not sure about,\nplease open an issue!\n\n\u003cdetails\u003e\n\u003csummary\u003e\nUnsupported features\n\u003c/summary\u003e\n\n- Networking\n  - Peer relays\n  - Exit Nodes (being one — advertising a default route; *using* one is supported)\n  - Exit node DNS (`ExitNodeDNSResolvers` — routing DNS through the exit node)\n  - Private DERP relays\n  - Subnet Routers (being one — advertising routes; *using* one is supported)\n- Platforms\n  - AIX\n  - Android\n  - BSDs\n  - iOS\n  - Plan9\n  - QNAP\n  - Synology DSM\n- Observability\n  - Client Metrics\n  - Endpoint Collection\n  - Device Posture Collection\n  - Log Streaming\n  - Network Flow Logs\n- Other Features\n  - Application Capabilities\n  - Automatic Key Rotation\n  - HTTPS Certificates\n  - Kubernetes\n  - Mullvad VPN\n  - Node Sharing\n  - Taildrive\n  - Taildrop\n  - Tailnet Lock — full enforcement (signature verification is wired, but the AUM-sync RPC that\n    supplies the trusted-key `Authority` is not yet built, so enforcement is inert; see\n    [SECURITY.md](SECURITY.md))\n  - Tailscale Funnel\n  - Tailscale Serve — the stored serve-config runtime and accept-loop (the `Path`/`Redirect`/`Proxy`/\n    `Text`/`TcpForward` handlers themselves are implemented)\n  - Tailscale SSH\n  - Tailscale Services\n  - Webhooks\n- Any other features not listed in \"Implemented\" or \"Coming Soon\"\n\n\u003c/details\u003e\n\n## Legal\n\n**This project is not associated with Tailscale Inc.** It is an independent, unofficial fork.\n\"Tailscale\" is a trademark of Tailscale Inc.; it is used here only to describe interoperability and\nthe upstream project this is forked from.\n\nWireGuard is a registered trademark of Jason A. Donenfeld.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeiserx%2Ftailscale-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeiserx%2Ftailscale-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeiserx%2Ftailscale-rs/lists"}