summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruvok cheetah2024-03-19 19:37:36 +0100
committeruvok cheetah2024-03-19 19:37:36 +0100
commit94fd6db6186ea78bb98bb7bbd5092ef7da92ac36 (patch)
tree8981c9d1e53cf8bcb62e8cb01f7c7e837982f2db
parente90d8566b369beb66df73eb2638905a86d07cf5f (diff)
Add my bird role
-rw-r--r--roles/uvok_bird/README.md38
-rw-r--r--roles/uvok_bird/defaults/main.yml10
-rw-r--r--roles/uvok_bird/handlers/main.yml9
-rw-r--r--roles/uvok_bird/meta/main.yml51
-rw-r--r--roles/uvok_bird/tasks/main.yml19
-rw-r--r--roles/uvok_bird/templates/clearnet.conf.j2289
-rw-r--r--roles/uvok_bird/tests/inventory2
-rw-r--r--roles/uvok_bird/tests/test.yml6
-rw-r--r--roles/uvok_bird/vars/main.yml2
9 files changed, 426 insertions, 0 deletions
diff --git a/roles/uvok_bird/README.md b/roles/uvok_bird/README.md
new file mode 100644
index 0000000..fd1fe7c
--- /dev/null
+++ b/roles/uvok_bird/README.md
@@ -0,0 +1,38 @@
+Role Name
+=========
+
+Start up my bird setup.
+
+Requirements
+------------
+
+Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
+
+Role Variables
+--------------
+
+A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
+
+Dependencies
+------------
+
+None
+
+Example Playbook
+----------------
+
+Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
+
+ - hosts: servers
+ roles:
+ - { role: username.rolename, x: 42 }
+
+License
+-------
+
+MIT
+
+Author Information
+------------------
+
+uvok (https://blog.uvokchee.de/). \ No newline at end of file
diff --git a/roles/uvok_bird/defaults/main.yml b/roles/uvok_bird/defaults/main.yml
new file mode 100644
index 0000000..927c6b8
--- /dev/null
+++ b/roles/uvok_bird/defaults/main.yml
@@ -0,0 +1,10 @@
+---
+# defaults file for bird
+uvok_bird_opts:
+ config_dir: "/tmp/bird/"
+ clearnet: false
+ dn42: false
+ use_fallback: false
+ preferred_ip: "::1"
+ prefixes: []
+ babel_if_name:
diff --git a/roles/uvok_bird/handlers/main.yml b/roles/uvok_bird/handlers/main.yml
new file mode 100644
index 0000000..9ace21c
--- /dev/null
+++ b/roles/uvok_bird/handlers/main.yml
@@ -0,0 +1,9 @@
+---
+# handlers file for uvok_bird
+
+- name: Check config
+ command: birdc configure check
+ listen: configure bird
+- name: apply config
+ command: birdc configure soft
+ listen: configure bird
diff --git a/roles/uvok_bird/meta/main.yml b/roles/uvok_bird/meta/main.yml
new file mode 100644
index 0000000..a5088bd
--- /dev/null
+++ b/roles/uvok_bird/meta/main.yml
@@ -0,0 +1,51 @@
+galaxy_info:
+ author: uvok
+ description: Start up my bird setup. Probably won't fit your needs.
+
+ # If the issue tracker for your role is not on github, uncomment the
+ # next line and provide a value
+ # issue_tracker_url: http://example.com/issue/tracker
+
+ # Choose a valid license ID from https://spdx.org - some suggested licenses:
+ # - BSD-3-Clause (default)
+ # - MIT
+ # - GPL-2.0-or-later
+ # - GPL-3.0-only
+ # - Apache-2.0
+ # - CC-BY-4.0
+ license: MIT
+
+ min_ansible_version: "2.16"
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ #
+ # Provide a list of supported platforms, and for each platform a list of versions.
+ # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+ # To view available platforms and versions (or releases), visit:
+ # https://galaxy.ansible.com/api/v1/platforms/
+ #
+ # platforms:
+ # - name: Fedora
+ # versions:
+ # - all
+ # - 25
+ # - name: SomePlatform
+ # versions:
+ # - all
+ # - 1.0
+ # - 7
+ # - 99.99
+
+ galaxy_tags: []
+ # List tags for your role here, one per line. A tag is a keyword that describes
+ # and categorizes the role. Users find roles by searching for tags. Be sure to
+ # remove the '[]' above, if you add tags to this list.
+ #
+ # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
+ # Maximum 20 tags per role.
+
+dependencies: []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
diff --git a/roles/uvok_bird/tasks/main.yml b/roles/uvok_bird/tasks/main.yml
new file mode 100644
index 0000000..c3ef063
--- /dev/null
+++ b/roles/uvok_bird/tasks/main.yml
@@ -0,0 +1,19 @@
+---
+# tasks file for uvok_bird
+- name: Ensure bird directory exists
+ ansible.builtin.file:
+ path: '{{ uvok_bird_opts.config_dir }}'
+ state: directory
+ mode: '0750'
+ owner: 'bird'
+ group: 'bird'
+- name: Install template
+ template:
+ src: clearnet.conf.j2
+ dest: '{{ uvok_bird_opts.config_dir }}/clearnet.conf'
+ mode: '0640'
+ owner: 'bird'
+ group: 'bird'
+ when:
+ - uvok_bird_opts.clearnet
+ notify: configure bird
diff --git a/roles/uvok_bird/templates/clearnet.conf.j2 b/roles/uvok_bird/templates/clearnet.conf.j2
new file mode 100644
index 0000000..9f75798
--- /dev/null
+++ b/roles/uvok_bird/templates/clearnet.conf.j2
@@ -0,0 +1,289 @@
+# {{ ansible_managed }}
+
+define CLEARNET_PREFIP = {{ uvok_bird_opts.preferred_ip }};
+
+# trs=transit
+ipv6 table t_myas_unfiltered;
+ipv6 table t_myas_trs;
+ipv6 table t_myas_babel;
+
+roa6 table clear_roa_v6;
+
+protocol rpki roa_clearnet1 {
+ roa6 { table clear_roa_v6; };
+ remote 10.2.0.1;
+ port 8282;
+ refresh 3600;
+ retry 600;
+ expire 7200;
+}
+
+protocol rpki roa_clearnet2 {
+ roa6 { table clear_roa_v6; };
+ remote 10.2.0.10;
+ port 8282;
+ refresh 3600;
+ retry 600;
+ expire 7200;
+}
+
+define BOGON_ASNS = [
+ 0, # RFC 7607
+ 23456, # RFC 4893 AS_TRANS
+ 64496..64511, # RFC 5398 and documentation/example ASNs
+ 64512..65534, # RFC 6996 Private ASNs
+ 65535, # RFC 7300 Last 16 bit ASN
+ 65536..65551, # RFC 5398 and documentation/example ASNs
+ 65552..131071, # RFC IANA reserved ASNs
+ 4200000000..4294967294, # RFC 6996 Private ASNs
+ 4294967295 ]; # RFC 7300 Last 32 bit ASN
+
+define BOGON_PREFIXES = [ ::/0, # Default route
+ ::/8+, # RFC 4291 IPv4-compatible, loopback, et al
+ 0100::/64+, # RFC 6666 Discard-Only
+ 2001:2::/48+, # RFC 5180 BMWG
+ 2001:10::/28+, # RFC 4843 ORCHID
+ 2001:db8::/32+, # RFC 3849 documentation
+ 2002::/16+, # RFC 7526 6to4 anycast relay
+ 3ffe::/16+, # RFC 3701 old 6bone
+ fc00::/7+, # RFC 4193 unique local unicast
+ fe80::/10+, # RFC 4291 link local unicast
+ fec0::/10+, # RFC 3879 old site local unicast
+ ff00::/8+ # RFC 4291 multicast
+ ];
+
+function reject_bogon_asns()
+int set bogon_asns;
+{
+ bogon_asns = BOGON_ASNS;
+
+ if ( bgp_path ~ bogon_asns ) then {
+ print "Reject: bogon AS_PATH: ", net, " ", bgp_path;
+ clearnet_add_filter(FILTER_BOGON_ASN);
+ }
+}
+
+function reject_bogon_prefixes()
+prefix set bogon_prefixes;
+{
+ bogon_prefixes = BOGON_PREFIXES;
+ if (net ~ bogon_prefixes) then {
+ print "Reject: Bogon prefix: ", net, " ", bgp_path;
+ clearnet_add_filter(FILTER_BOGON_PREFIX);
+ }
+}
+
+define PROBLEM_PREFIXES = [
+];
+
+function reject_problem_prefixes()
+prefix set problem_prefixes;
+{
+ problem_prefixes = PROBLEM_PREFIXES;
+ if (net ~ problem_prefixes) then {
+ print "Reject: Problematic prefix: ", net, " ", bgp_path;
+ clearnet_add_filter(FILTER_PROBLEM_PREFIX);
+ }
+}
+
+function reject_long_aspaths()
+{
+ if ( bgp_path.len > 50 ) then {
+ clearnet_add_filter(FILTER_LONG_ASPATH);
+ }
+}
+
+function reject_small_prefixes()
+{
+ if (net.len > 55 && net.type = NET_IP6) then {
+ print "Reject: Too small prefix: ", net, " ", bgp_path;
+ clearnet_add_filter(FILTER_SMALL_V6_PREFIX);
+ }
+}
+
+function reject_roa_rpki()
+{
+ if ( roa_check(clear_roa_v6, net, bgp_path.last_nonaggregated) = ROA_INVALID ) then {
+ clearnet_add_filter(FILTER_ROA_RPKI);
+ }
+}
+
+function clearnet_common_import() {
+ reject_bogon_asns();
+ reject_bogon_prefixes();
+ reject_long_aspaths();
+ reject_small_prefixes();
+ reject_problem_prefixes();
+ reject_roa_rpki();
+ honor_graceful_shutdown();
+}
+
+filter myas_export
+{
+ if (proto = "myprefix") then {
+ accept;
+ }
+ reject;
+}
+
+# route collector
+filter myas_f_rc
+{
+# export IXP routes after all
+# if ( clearnet_is_ixp() ) then reject;
+ if (source = RTS_BGP) then accept;
+ if (proto = "myprefix") then accept;
+ reject;
+};
+
+protocol static myprefix {
+{% for prefix in uvok_bird_opts.prefixes %}
+ route {{ prefix }} reject;
+{% endfor %};
+
+ ipv6 {
+ # needs to be in unfiltered - because that's where I'm exporting from
+ table t_myas_unfiltered;
+ import all;
+ export none;
+ };
+}
+
+protocol direct {
+ ipv6 { table t_myas_babel; };
+ interface "myas_int";
+};
+
+template bgp pt_clearnet {
+ local as CLEARNET_ASN;
+
+ graceful restart on;
+ long lived graceful restart on;
+
+ prefer older on;
+
+ # Neighbor as must be first route as
+ enforce first as on;
+ # faster updates
+ enable extended messages on;
+
+ # defaults anyway
+ enable route refresh on;
+ interpret communities on;
+ direct;
+
+ # higher better
+ default bgp_local_pref 100;
+
+ # my value - lower better
+ default bgp_med 100;
+
+ ipv6 {
+ # start by importing into the unfiltered table
+ table t_myas_unfiltered;
+
+ # for inspection who's evil
+ import keep filtered;
+ # for RPKI / ROA
+ import table on;
+
+ import filter {
+ clearnet_import_transit();
+ clearnet_common_import();
+ accept;
+ };
+
+ export filter myas_export;
+ };
+}
+
+# route collector
+template bgp pt_rc from pt_clearnet {
+ multihop;
+
+ # yes, use unfiltered table for export
+ # I wanna shame garbish announcers publically! ;)
+ ipv6 {
+ add paths tx;
+ import none;
+ export filter myas_f_rc;
+ };
+}
+
+{% if uvok_bird_opts.babel_if_name %}
+protocol babel p_myas_babel {
+ ipv6 {
+ table t_myas_babel;
+ import where source ~ [RTS_DEVICE, RTS_BABEL];
+ export where source ~ [RTS_DEVICE, RTS_BABEL];
+ };
+
+ interface "{{ uvok_bird_opts.babel_if_name }}" {
+ };
+}
+{% endif %}
+
+# pipe babel table => bgp table for next-hop resolution?
+protocol pipe {
+ table t_myas_babel;
+ peer table t_myas_trs;
+ import none;
+ export where source ~ [RTS_BABEL];
+}
+
+# EXPORT FROM unfilteed TO filtered trs table
+protocol pipe {
+ table t_myas_unfiltered;
+ peer table t_myas_trs;
+ import none;
+ export filter {
+ if ( bgp_large_community ~ [(CLEARNET_ASN, LC_FILTERED, *)] ) then {
+ reject;
+ }
+ accept;
+ };
+}
+
+protocol kernel p_myas_i {
+# scan time 20;
+ kernel table 150;
+
+ ipv6 {
+ table t_myas_babel;
+ import none;
+ export filter {
+ if (source != RTS_BABEL) then {
+ print "SHOULD NOT HAPPEN: export babel to kernel: ", net, " from", source;
+ reject;
+ }
+ krt_prefsrc = CLEARNET_PREFIP;
+ accept;
+ };
+ };
+};
+
+protocol kernel pk_myas_out {
+ kernel table 100;
+
+ ipv6 {
+ table t_myas_trs;
+ import none;
+ export filter {
+ krt_prefsrc = CLEARNET_PREFIP;
+ if (source = RTS_BGP) then {
+ accept;
+ }
+{% if uvok_bird_opts.use_fallback %}
+ if (proto = "myas_def_fallb") then {
+ accept;
+ }
+{% endif %}
+ reject;
+ };
+ };
+};
+
+include "/etc/bird/clear_peers/*.conf";
+{% if uvok_bird_opts.use_fallback %}
+include "clear_fallback.conf";
+{% endif %}
diff --git a/roles/uvok_bird/tests/inventory b/roles/uvok_bird/tests/inventory
new file mode 100644
index 0000000..878877b
--- /dev/null
+++ b/roles/uvok_bird/tests/inventory
@@ -0,0 +1,2 @@
+localhost
+
diff --git a/roles/uvok_bird/tests/test.yml b/roles/uvok_bird/tests/test.yml
new file mode 100644
index 0000000..316407d
--- /dev/null
+++ b/roles/uvok_bird/tests/test.yml
@@ -0,0 +1,6 @@
+---
+- name: "Test play?"
+ hosts: localhost
+ remote_user: root
+ roles:
+ - uvok_bird
diff --git a/roles/uvok_bird/vars/main.yml b/roles/uvok_bird/vars/main.yml
new file mode 100644
index 0000000..f543c41
--- /dev/null
+++ b/roles/uvok_bird/vars/main.yml
@@ -0,0 +1,2 @@
+---
+# vars file for uvok_bird