{"id":13676851,"url":"https://github.com/wgnet/befw","last_synced_at":"2025-04-05T11:11:04.568Z","repository":{"id":56646744,"uuid":"180835084","full_name":"wgnet/befw","owner":"wgnet","description":"BEFW","archived":false,"fork":false,"pushed_at":"2025-01-08T13:04:26.000Z","size":2659,"stargazers_count":117,"open_issues_count":0,"forks_count":14,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-29T10:09:26.681Z","etag":null,"topics":["based","consul","dynamic","firewall","for","linux"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wgnet.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-04-11T16:39:20.000Z","updated_at":"2025-01-08T13:04:30.000Z","dependencies_parsed_at":"2023-12-14T21:26:37.678Z","dependency_job_id":"ca03b434-6bc2-43e9-b669-b26030ef5b21","html_url":"https://github.com/wgnet/befw","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wgnet%2Fbefw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wgnet%2Fbefw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wgnet%2Fbefw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wgnet%2Fbefw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wgnet","download_url":"https://codeload.github.com/wgnet/befw/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247325693,"owners_count":20920714,"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":["based","consul","dynamic","firewall","for","linux"],"created_at":"2024-08-02T13:00:33.849Z","updated_at":"2025-04-05T11:11:04.545Z","avatar_url":"https://github.com/wgnet.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# BEFW project\n###### Dynamic Host-Based Firewall\n# Intro\n**BEFW** is a couple of golang-written tools that are eligible to maintain dynamic firewall rules across the datacenter(s).\nThe approach is based on the service discovery concept: if we know there's a service, we can protect it. If we know there's a client for the service, we can allow him to connect to.\nBEFW is using consul service catalog to store services ( with their tcp/udp ports ) and is using consul key-value storage to store services clients.\nIt's just a bit smarter than ```curl localhost:8200/v1/agent/services|perl -e '\u003cscript\u003e'|iptables-restore```, but 'a bit' is significant here.\n# Requirements\n- Any modern Linux distro with iptables \u0026 ipset support.\n- You must have at least one consul cluster with acl support enabled.\n- You must have consul agent on every node that runs befw.\n- We provide the only PuppetDB orchestration provider. You may need to develop yourth.\n\n# How to build\n```\ngo install github.com/wgnet/befw/cmd/befw-cli\ngo install github.com/wgnet/befw/cmd/befw-firewalld\ngo install github.com/wgnet/befw/cmd/befw-sync\n```\n***\n# Deployment scheme\n**BEFW** is not only tools but the approach too. If you build dynamic firewall from scratch, you may use our deployment guide.\n## Consul cluster\n1. [Install](https://www.consul.io/docs/install/index.html) regular consul cluster ( or federated cluster ) with N ( N % 2 == 1) servers and M agents. Each server must have consul agent running.\n2. Push [some data](samples/post.sh) and enjoy\n### ACLs\nTo protect your firewall configuration from unauthorized changes you need to create at least 3 acl sets on your consul cluster.\nTo enable ACL support please read this [article](https://www.consul.io/docs/guides/acl-legacy.html).\n#### anonymous ACL\nAllows anyone to read data from firewall ( usable for monitoring, metrics \u0026 UI for end users). [Example](samples/anonymous.acl).\n#### node/agent ACL\nAllows node/agent to read firewall configuration and register services. [Example](samples/node.acl).\n#### Commit/Master ACL\nAllows 3pc software to write firewall configuration and purge expired data. [Example](samples/master.acl).\n## Configuration\nWe use single consul datacenter to store firewall KV and we call it *dc*. You should specify this datacenter into configuration file.\nWe use multiple consul datacenters ( one per site ) to store services \u0026 local KVs.\nYou may use single-dc configuration, specify it's name as *dc* though.\n## Default firewall rules\n3. Change default [**iptables template**](samples/iptables.rules)\n## Service\n4. Install \u0026 launch befw-firewalld service on every agent node\n5. Edit [sample configuration](samples/befw.conf) and place it to /etc/befw.conf.  Options:\n    - firewall (values: \"nft\"|\"nftc7\", default: \"\") - Change firewall provider: nft - nftables, nftc7 - legacy nftables 0.8 (centos7), otherwise - iptables/ipset\n6. Place [sample service](samples/service.json) to *services dir* and see what will happen\n## Puppet/Hiera/PuppetDB\n*We use puppet to do items 3-6 and below as we have a huge puppet installation. Skip this if you don't.*\nPuppet provides a great way to enumerate services on every node. You can just add something like that in every role/application-definition class:\n```puppet\nfile { \"/etc/befw.service.d/${title}.json\":\n    ensure  =\u003e file,\n    content =\u003e \"\u003c-- json here --\u003e\",\n}\n```\nThis will provide your services in consul automagically. Just a few patches once will save your time forever.\nSee [samples](samples/puppet/) for more information.\n### befw-sync\nHere, in Wargaming, we also use hiera \u0026 puppetdb to provide both services \u0026 clients for our services. The idea is that if we can collect \u0026 commit something to puppetdb ( like 'i_need_this_service_to_work'), that we can just grab it from puppetdb and store into consul.\n**befw-sync** does this job, looking into puppetdb for a corresponding *resource* and grabbing parameters to push to consul KV storage.\nSee [sample config](samples/befw.sync.conf) to get into, but we doubt it is useful if you don't have such huge puppet installation on your world.\n# Managing rules\n## Adding new service\n- Place a service file to *services* directory or\n- Post a http request to local consul agent ( v1/agent/register ) or\n- Allow consul-supported software ( like vault ) to manage it on its own\n\n**N.B.** use tag 'befw' to generate rules for this service. Use tags 'port/protocol' ( like '80/tcp' ) to specify *additional* ports for the service.\n## Adding new rules\n- Place ip/network and expiry value to KV storage on *dc* datacenter or\n- Place alias and expiry value to KV storage on *dc* datacenter or\n- Place a new data to alias definition to KV storage on *dc* datacenter\n\n**N.B.** You can specify world, dc or node level while placing the rules.\n### Examples\n```go\nconsul.KV().Put(\"befw/$service$/service_tcp_443/192.168.1.1/30\", time.now()+2*week)\nconsul.KV().Put(\"befw/$service$/dc/service_tcp_443/192.168.1.1/30\", time.now()+2*week)\nconsul.KV().Put(\"befw/$service$/dc/nodename/service_tcp_443/192.168.1.1/30\", time.now()+2*week)\nconsul.KV().Put(\"befw/$service$/service_tcp_443/$trusted$\", -1) // \u003c0 never expires\nconsul.KV().Put(\"befw/$alias$/$trusted$/192.168.1.1.30\", time.now()+1*hour)\n```\n## Tools\n[**pusher**](samples/pusher.py) is a very primitive python (2.7) tool to manage befw manually. Please avoid using it in production.\n**Usage**: ./pusher.py list|add|rm|clist|cadd|crm  [opts]\n**Config file**: ~/.pusher.conf\n```bash\nhost=localhost\nport=8500\ndc=consul\ntoken=2375a28a-75ec-4b5f-a30f-3e68f8239a0a\n```\n**Example usage**:\n```bash\n# no clients for service\n$ ./pusher.py clist myown_tcp_5672\n[+] DC= dc , Node= node\n# adding new one for level 3 ( node )\n$ ./pusher.py cadd myown_tcp_5672 127.0.0.1 3\n[+] DC= dc , Node= node\nAdded 127.0.0.1 to befw/dc/node/myown_tcp_5672/127.0.0.1 with expiry=1554896188\n# yes we have it on KV now\n$ ./pusher.py clist myown_tcp_5672\n[+] DC= dc , Node= node\nbefw/dc/node/myown_tcp_5672/\n *127.0.0.1\n# deleteting 127.0.0.1 from all levels\n$ ./pusher.py crm myown_tcp_5672 127.0.0.1\n[+] DC= dc , Node= node\nDeleting befw/myown_tcp_5672/127.0.0.1\nDeleting befw/dc/myown_tcp_5672/127.0.0.1\nDeleting befw/dc/node/myown_tcp_5672/127.0.0.1\n# no clients found\n$ ./pusher.py clist myown_tcp_5672\n[+] DC= dc , Node= node\n$\n```\n# Changelog\nSee [CHANGELOG](CHANGELOG.md).\n# Known issues\nSee [ISSUES](ISSUES.md).\n# Contributing\nSee [CONTRIB](CONTRIB.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwgnet%2Fbefw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwgnet%2Fbefw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwgnet%2Fbefw/lists"}