使用 Bird 宣告一个地址(BYOIP)

使用 Bird 宣告一个地址(BYOIP)

发表于 2023/08/14 更新于 2023/08/14 248 字 1 分钟
AI 摘要 由 AI 自动生成

|

无论如何,你得先找一个支持 BGP 的上游,它可能能支持自助开通 BGP 服务,或者通过 Ticket 让你提交 LOA。政策上的事情不在这个文章中讨论。

本文以 Debian11 和 Bird2 为例。

配置一个虚拟网卡

直接改 /etc/network/interfaces 的配置,可以 ifup ifdown 控制。

虚拟 IP 写 /128 或者 /32,否则会出现问题。

auto dummy0
iface dummy0 inet6 static
   address IPv6/128
   pre-up ip link add $IFACE type dummy
   post-down ip link delete $IFACE type dummy

auto dummy1
iface dummy1 inet static
   address IPv4/32
   pre-up ip link add $IFACE type dummy
   post-down ip link delete $IFACE type dummy

拉起虚拟网卡。

ifdown dummy0
ifup dummy0

配置 Bird

修改 Bird 配置,这里是一个示例的配置,可以按这个来,这里不做配置解释,想了解配置的意思可以看一下 Bird 的文档。

vim /etc/bird/bird.conf
# 下面是配置文件
log "/var/log/bird.log" { debug, trace, info, remote, warning, error, auth, fatal, bug };

define ROUTER_ID = 你机器的公网v4地址; # 例如 6.6.6.6
define LOCAL_ASN = 你的AS号; # 例如 114514
define LOCAL_ASN_IPV6_PREFIX_SET = [你要宣告的IPv6地址段]; # 多段用,隔开,例如 xxxxxx::/48,yyyyyy::/48

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_V4 = [
    0.0.0.0/8+,             # RFC 1122 'this' network
    10.0.0.0/8+,            # RFC 1918 private space
    100.64.0.0/10+,         # RFC 6598 Carrier grade nat space
    127.0.0.0/8+,           # RFC 1122 localhost
    169.254.0.0/16+,        # RFC 3927 link local
    172.16.0.0/12+,         # RFC 1918 private space
    192.0.2.0/24+,          # RFC 5737 TEST-NET-1
    192.88.99.0/24+,        # RFC 7526 deprecated 6to4 relay anycast. If you wish to allow this, change `24+` to `24{25,32}`(no more specific)
    192.168.0.0/16+,        # RFC 1918 private space
    198.18.0.0/15+,         # RFC 2544 benchmarking
    198.51.100.0/24+,       # RFC 5737 TEST-NET-2
    203.0.113.0/24+,        # RFC 5737 TEST-NET-3
    224.0.0.0/4+,           # multicast
    240.0.0.0/4+            # reserved
];

define BOGON_PREFIXES_V6 = [
    ::/8+,                  # RFC 4291 IPv4-compatible, loopback, et al
    0064:ff9b::/96+,        # RFC 6052 IPv4/IPv6 Translation
    0064:ff9b:1::/48+,      # RFC 8215 Local-Use IPv4/IPv6 Translation
    0100::/64+,             # RFC 6666 Discard-Only
    2001::/32{33,128},      # RFC 4380 Teredo, no more specific
    2001:2::/48+,           # RFC 5180 BMWG
    2001:10::/28+,          # RFC 4843 ORCHID
    2001:db8::/32+,         # RFC 3849 documentation
    2002::/16+,             # RFC 7526 deprecated 6to4 relay anycast. If you wish to allow this, change `16+` to `16{17,128}`(no more specific)
    3ffe::/16+, 5f00::/8+,  # 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
];

router id ROUTER_ID;

function is_bogon_prefix() {
    case net.type {
        NET_IP4: return net ~ BOGON_PREFIXES_V4;
        NET_IP6: return net ~ BOGON_PREFIXES_V6;
        else: print "is_bogon_prefix: unexpected net.type ", net.type, " ", net; return false;
    }
}

function is_bogon_asn() {
    if bgp_path ~ BOGON_ASNS then return true;
    return false;
}

# 公网上约定俗成的最小前缀长度是 24(IPv4)和 48(IPv6),所以要在导出的时候过滤
function net_len_too_long(){
    case net.type {
        NET_IP4: return net.len > 24; # IPv4 CIDR 大于 /24 为太长
        NET_IP6: return net.len > 48; # IPv6 CIDR 大于 /48 为太长
        else: print "net_len_too_long: unexpected net.type ", net.type, " ", net; return false;
    }
}

function bgp_export() {
    if net_len_too_long() then return false;
    if source != RTS_STATIC then return false;
    if net !~ LOCAL_ASN_IPV6_PREFIX_SET then return false;
    return true;
}


template bgp bgp_tpl {
    graceful restart;
    local as LOCAL_ASN;
    ipv6 {
        import filter {
            if net_len_too_long() then reject;
            if is_bogon_prefix() then reject;
            if is_bogon_asn() then reject;
            if proto = "noAnnounce" then reject;
            accept;
        };
        export where bgp_export();
    };
}

protocol device {
    scan time 5;
}

protocol kernel {
        ipv6 {
        export all;
    };
}

protocol static noAnnounce {
    ipv6;
    route 宣告的地址段 via 本机网卡的IPv6地址; # 例如 route yyyyyy::/48 via xxxxx::1;
}

protocol static Announce {
    ipv6;
    route 宣告的地址段 reject; # 例如 xxxxx::/48
}


protocol bgp OOOOH from bgp_tpl {
    source address 本机网卡的IPv6地址;
    multihop 2; # 跳数
    neighbor 邻居地址 as 邻居AS号; # 你的上游会告诉你的
    #password "密码"; # Peer 密码,有就写没有就注释掉好了
    ipv6 {
        export limit 15;
    };
}

创建 log 文件并授权,省的 Bird 因为权限问题起不来了。

touch /var/log/bird.log
chown bird:bird /var/log/bird.log

重启 Bird,或重载配置文件。

systemctl restart bird # 或者 birdc configure

验证

先看一下你的邻居建立起来没有。

birdc show protocol all

OOOOH      BGP        ---        up     2023-08-03    Established
  BGP state:          Established

Established 了,说明你俩是 OK 的。

等你的上游放通你,最后以达到全球路由表有你的记录,你就可以在任意地方访问到你的 IP 了。

作者: 小谈谈
声明: 本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。