{"id":31701865,"url":"https://github.com/getlantern/geneva","last_synced_at":"2025-10-08T21:09:35.133Z","repository":{"id":39879507,"uuid":"444207620","full_name":"getlantern/geneva","owner":"getlantern","description":"Port of Geneva to Go","archived":false,"fork":false,"pushed_at":"2024-03-15T17:26:33.000Z","size":218,"stargazers_count":27,"open_issues_count":1,"forks_count":6,"subscribers_count":10,"default_branch":"main","last_synced_at":"2024-06-19T02:57:46.128Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/getlantern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2022-01-03T21:42:46.000Z","updated_at":"2024-02-08T12:26:50.000Z","dependencies_parsed_at":"2024-06-19T02:56:54.562Z","dependency_job_id":null,"html_url":"https://github.com/getlantern/geneva","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/getlantern/geneva","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlantern%2Fgeneva","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlantern%2Fgeneva/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlantern%2Fgeneva/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlantern%2Fgeneva/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/getlantern","download_url":"https://codeload.github.com/getlantern/geneva/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getlantern%2Fgeneva/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000716,"owners_count":26082837,"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","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"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":[],"created_at":"2025-10-08T21:09:29.945Z","updated_at":"2025-10-08T21:09:35.128Z","avatar_url":"https://github.com/getlantern.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# geneva, an implementation of Geneva rules for Go\n[![Go Actions Status](https://github.com/getlantern/geneva/actions/workflows/run-tests.yaml/badge.svg)](https://github.com/getlantern/geneva/actions)\n[![Coverage Status](https://coveralls.io/repos/github/getlantern/geneva/badge.svg?branch=main)](https://coveralls.io/github/getlantern/geneva?branch=main)\n\nThis is a reimplementation of the client- and server-side rule processing mechanisms of the [Geneva][geneva] project.\n\nGeneva is both a method to describe ways of manipulating packets to attempt to circumvent censorship, and a genetic\nalgoritm (_GENetic EVAsion_) that one can deploy to discover new circumventions. (This package does not implement the\ngenetic algorithm.) More broadly, though, one can encode arbitrary instructions for packet manipulation using Geneva\nrules as a sort of \"standard syntax\", although the use case outside of censorship circumvention may be somewhat tenuous.\n\nThis package aims to implement the same triggers and actions that the Geneva project's canonical Python package\ndoes. _Please note: this package is a work-in-progress, and there are still things left to implement._\n\n## Quick Background\n\nGeneva rules are called _strategies_. A strategy consists of zero or more _action trees_ that can be applied to inbound\nor outbound packets. The actions trees define both a _trigger_ and a tree of actions to take on a packet if the trigger\nmatches. The result of an action tree will be zero or more packets that should replace the original packet, which then\ncan be reinjected into the host OS' network stack.\n\n## Strategies, Forests, and Action Trees\n\nLet's work from the top down. A strategy, conceptually, looks like this:\n\n    outbound-forest \\/ inbound-forest\n\n_outbound-forest_ and _inbound-forest_ are ordered lists of _(trigger, action tree)_ pairs. The Geneva paper calls these\nordered lists _forests_. The outbound and inbound forests are separated by the `\\/` characters (that is a backslash\nfollowed by a forward-slash); if the strategy omits one or the other, then that side of the `\\/` is left empty. For\nexample, a strategy that only includes an outbound forest would take the form `outbound \\/`, whereas an inbound-only\nstrategy would be `\\/ inbound`.\n\nThe original Geneva paper does not have a name for these (trigger, action tree) pairs. In practice, however, the Python\ncode actually defines an action tree as a (trigger, action) pair, where the \"action\" is the root of a tree of\nactions. This package follows this nomenclature as well.\n\nA real example, taken from the [original paper][geneva-paper] (pg 2202), would look like this:\n\n    [TCP:flags:S]-\n       duplicate(\n          tamper{TCP:flags:replace:SA}(\n             send),\n           send)-| \\/\n    [TCP:flags:R]-drop-|\n\nIn this example, the outbound forest would trigger on TCP packets that have just the `SYN` flag set, and would perform a\nfew different actions on those packets. The inbound forest would only apply to TCP packets with the `RST` flag set, and\nwould simply drop them. Each of the forests in the example are made up of a single (trigger, action tree) pair.\n\nThe outbound forest for the above action in graph form looks like this:\n\n![Inbound Forest Graph](img/rule_example.svg)\n\nIn a forest, each action tree must adhere to the syntax `[trigger]-action-|`. Currently, the parser for this package is\nstricter than the original; this is a bug.\n\n## Triggers\n\nA trigger defines a way to match packets so that an action tree can be applied to them. In the example above, the first\ntrigger is `[TCP:flags:S]`. This is a trigger that matches on the TCP segment's _flags_ field, and requires that only\nthe `SYN` flag be set. (Note that this trigger will not fire for packets that have, i.e., both `SYN` and `ACK` set.) If\nthe packet is not a TCP packet, or the flags do not match exactly, then this trigger will not fire.\n\n## Actions\n\nAn action simply encodes steps to manipulate a packet. There are a number of actions described in the Geneva paper:\n\n### send\n\nThe \"send\" action simply yields the given packet. (A quirk—what the paper calls canonical syntax—is to elide any \"send\"\nactions in the action tree. For instance, the action \"duplicate(,)\" is equivalent to \"duplicate(send,send)\". Bear this\nin mind when reading Geneva strategies!)\n\n### drop\n\nThe \"drop\" action discards the given packet.\n\n### duplicate(a1, a2)\n\nThe \"duplicate\" action copies the original packet, then applies action `a1` to the original and `a2` to the copy. For\nexample, if `a1` and `a2` are both \"send\" actions, then the action will yield two packets identical to the first.\n\n### fragment{protocol:offset:inOrder}(a1, a2)\n\nThe \"fragment\" action takes the original packet and fragments it, applying `a1` to one of the fragments and `a2` to the\nother. Since both the IP and TCP layers support fragmentation, the rule must specify which layer's payload to\nfragment. The first fragment will include up to _offset_ bytes of the layer's payload; the second fragment will contain\nthe rest. As an example, given an IPv4 packet with a 60-byte payload and an 8-byte offset, the first fragment will have\nthe same IP header as the original packet (aside from the fields that must be fixed) and then the first eight bytes of\nthe payload. The second fragment will contain the other 52 bytes. (You can also indicate that the fragments be returned\nout-of-order; i.e., reversed, by specifying \"False\" for the _inOrder_ argument.)\n\n### tamper{protocol:field:mode[:newValue]}(a1)\n\nThe \"tamper\" action takes the original packet and modifies it in some fashion, depending on the protocol, field, and\nmode given. There are two modes: replace and corrupt. The \"replace\" mode will replace the value of the given field with\nnewValue, while the \"corrupt\" mode will replace the value with random data. (Note that there are other modes that the\nPython code supports that are not defined in the original Geneva paper.)\n\nAdditionally, note that not all actions are valid for both inbound and outbound directions. The Python code mentions\nthat \"branching actions are not supported on inbound trees\". Practically, this means that the duplicate and fragment\nactions can only be applied to outbound packets, while the sleep, drop, and tamper actions can apply to packets of\neither direction. (Note that this package does not currently enforce this; this is also a bug.)\n\n## Disclaimer\n\nCurrently only IPv4 and TCP are supported. There are plans to add support for UDP in the future (although pull requests\nare welcome! Look at `TCPTamperAction` and `IPv4TamperAction` in `actions/tamper_action.go` as examples.\n`UDPTamperAction` must implement the `actions.Action` interface). There are no plans at the moment to add support \nfor IPv6.\n\n## Credits\n\nSee https://censorship.ai for more information about Geneva itself.\n\n\n[geneva]: https://censorship.ai\n[geneva-paper]: https://geneva.cs.umd.edu/papers/geneva_ccs19.pdf\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetlantern%2Fgeneva","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetlantern%2Fgeneva","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetlantern%2Fgeneva/lists"}