Imagem aqui!

Engenharia de Tráfego BGP: Unicast

Bernardo Soares
TechRebels
Published in
15 min readAug 28, 2019

--

Engenharia de tráfego, por definição, significa otimizar a performance de uma rede através da manipulação do fluxo de trafego. Em outras palavras, podemos dizer que o objetivo de qualquer prática de engenharia de tráfego é influenciar o caminho em que um determinado fluxo de pacotes deve seguir.

Seja qual for o requisito, o BGP fornece as ferramentas necessárias para que você possa manipular o tráfego que entra ou sai de sua rede de uma forma bem granular, suprindo tanto as necessidades mais simples quanto cenários mais avançados.

Sendo o acesso a internet um recurso essencial nos dias de hoje, a engenharia de tráfego pode ser utilizada como um diferencial estratégico, permitindo endereçar as mais diversas necessidades de redundância(fail-over) e distribuição de carga (load sharing).

Neste post falaremos sobre as mais comuns ferramentas do BGP utilizadas para influenciar o fluxo de tráfego que entra (ingress) ou sai (egress) de um determinado AS. Ressalto que o foco aqui é no BGP na camada de internet, estando fora do nosso escopo o roteamento na camada de core/agg da rede interna.

Se gostou do conteúdo, peço para dar “palmas” aí do lado esquerdo e compartilhar com outros do ramo. Não se esqueça de seguir a mim e ao TechRebels clicando follow aí embaixo :)

Unicast X Anycast

Para saber melhor o que pode ser feito em termos de otimização, primeiro devemos entender se estamos lidando com um perfil de tráfego Unicast ou Anycast. A diferença entre estes dois perfis de tráfego é simples: um endereço Unicast está presente em apenas um site (ou AS). Ou seja, os pacotes sempre chegam no mesmo lugar. Do contrário, um endereço Anycast vai ser anunciado por mais de um site. Isso infere que um anúncio unicast para a internet deve (na maioria das vezes) estar acessível por toda a internet. Possui um escopo “global” de propagação. No exemplo abaixo, vemos o prefixo 192.0.2.0/24 anunciado de um site na América do Sul sendo propagado por toda a internet. Todo tráfego com este destino será direcionado à este site.

Já com o Anycast, muitas vezes deve-se utilizar outras técnicas para controlar a propagação de um determinado anúncio, visto que o objetivo de tal técnica e oferecer um serviço o mais próximo possível de seus clientes. Isso consiste em manipular o escopo de propagação, o que pode significar um escopo regional, continental, etc por meio de restringir determinados anúncios a determinadas partes da internet. Um anúncio Anycast nem sempre vai existir em toda a tabela da internet. Neste exemplo, temos o prefixo 192.0.2.0/24 agora sendo anunciado a partir de dois PoPs: um na América do Sul, o outro na Asia. O escopo de propagação destes prefixos está marcado em roxo e verde, respectivamente. Como resultado, temos o prefixo originado na America do Sul sendo propagado para a América do Norte, e o prefixo originado da Asia sendo propagado para a Europa. Desta forma, os clientes destas regiões (onde não há um pop local) serão direcionados de acordo com o que definimos.

Hoje falaremos das técnicas normalmente utilizadas para um perfil Unicast (restrito a apenas um PoP) — com o intuito de manipular o tráfego para um site específico (isto é, otimizando a utilização dos links upstream). Veremos mais de perto os detalhes específicos para engenharia de tráfego anycast em outro post.

Direção do Tráfego: Ingress ou Egress?

Quando pensamos em traffic engineering, devemos primeiro responder a seguinte questão: Em qual sentido devo trabalhar?

Eventualmente, ambos os sentidos serão avaliados. No entanto, manipular o tráfego em cada sentido é uma atividade independente.

Manipular o tráfego no sentindo “egress”, ou seja, o tráfego que sai de um determinado AS, consiste em influenciar o processo de decisão BGP localmente para preferir um ponto específico de saída do AS. No sentido inverso, a manipulação do tráfego “ingress” consiste em influenciar a decisão de roteamento de outros AS.

Atributos BGP

Neste ponto, já sabemos que para influenciar a decisão de roteamento (seja dentro ou fora do AS), devemos manipular os atributos BGP. Cada atributo pode ser alterado para obter um determinado resultado, visto que diferentes atributos são avaliados em passos diferentes no algoritmo de seleção BGP.

Estes atributos são divididos em duas categorias: “Well known” e “Optional”.

Atributos Well known são interpretados por todas as implementações BGP, por exemplo: Next-hop, Origin, AS-PATH, Local Pref. Por outro lado, atributos do tipo “Optional” podem ou não ser reconhecidos pela implementação BGP de uma determinada plataforma ou daemon. Alguns atributos Optional são: MED, Community, Originator-ID.

Segue abaixo uma tabelinha para referencia:

Imagem original aqui

Single/Dual homed ou Multi homed?

Uma outra informação que devemos ter em mãos antes de começar é qual o modelo do acesso a internet (ou qualquer que seja o upstream). Nem vamos falar de single homed, pois quando só existe uma entrada e saída, não há muito o que fazer. O trabalho já está feito :)

No caso de dual homed, estamos falando de um equipamento CE (do nosso lado) com duas ou mais conexões ao mesmo ISP (o mesmo ASN).

Dual homed, com acesso no mesmo PE
Dual homed, com acesso a PEs distintos

No multi homed, teremos um ou mais de um equipamento do lado CE — se conectando a upstream distintos (ASN diferentes).

Single multi homed
Dual multi homed

Manipulando a saída do tráfego: Egress

Para controlar a decisão de roteamento na saída, podemos utilizar os atributos weight, local-pref e MED. A utilização de cada atributo varia com o tipo de conectividade que temos, considerando ambos os lados.

Weight

O atributo Weight é implementado apenas em plataformas Cisco (IOS, XE, XR). O Weight é um atributo utilizado localmente, e nunca é anunciado aos peers em uma mensagem update. Em outras palavras, o weight vai alterar a preferência local de um determinado prefixo, e essa indicação de “melhor saída” não será repassado aos gateways internos — fazendo com que o seu uso seja mais adequado quando temos uma topologia “dual homed” ou “single multi homed” — apenas um equipamento do lado CE. No exemplo abaixo, podemos alterar o weight de alguns prefixos para preferir um link ao outro para um determinado prefixo ou grupo de prefixos.

Neste exemplo simples, preferimos a saída pelo Link A (PE-A) e utilizamos o link B como backup.

CE-A:route-map LINK-A permit 10
set weight 10
!
route-map LINK-B permit 10
!
router bgp 65000
neighbor PE-A route-map LINK-A in
neighbor PE-B route-map LINK-B in
!

MED

O atributo MED (também chamado de “metric”) é um atributo “optional non-transitive” — ou seja, não necessariamente precisa ser reconhecido pela implementação BGP, e so é repassado a outros neighbors caso seja reconhecido. Na prática, as implementações BGP em plataformas Cisco (IOS, XE, XR), Juniper , assim como muitas outras (Quagga, FRR, Arista, etc etc) reconhecem tal atributo.

Um fator a se considerar é que a comparação da MED so é feita (por default) para prefixos recebidos do mesmo AS vizinho — sugerindo uma topologia “dual homed” (conectados a apenas um AS upstream). Porém, podemos alterar este comportamento utilizando a feature “bgp always compare med” para que a MED seja avaliada para anúncios recebidos de AS distintos — ou seja, também podemos utilizar a MED no cenário “multi homed”.

Por fim, algumas plataformas implementam a comparação não determinística do atributo MED — fazendo com que os resultados não sejam sempre como o esperado. Para evitar este problema, habilitar a comparação determinística de MED é recomendado.

CE-A:ip prefix-list MED-50 permit 172.16.10.0/24
!
route-map LINK-A permit 10
match ip address prefix-list MED-50
set metric 50
!
route-map LINK-A permit 200
set metric 100
!
router bgp 65000
neighbor PE-A route-map LINK-A in
!
CE-B:set policy-options prefix-list MED-50 172.16.20.0/24
set policy-options policy-statement LINK-B term MED-50 from prefix-list MED-50
set policy-options policy-statement LINK-B term MED-50 then metric 50
set policy-options policy-statement LINK-B term MED-50 then accept
set policy-options policy-statement LINK-B term MED-100 then metric 100
!
<snip>
set protocols bgp group AS2914 neighbor PE-B import LINK-B
!
Gateway interno:router bgp 65000
bgp always-compare-med
bgp deterministic-med

!
ouset protocols bgp path-selection always-compare-med

Por fim, vale lembrar que a comparação da MED só vai ser feita caso a decisão de melhor caminho não tenha sido completada; ou seja, os atributos Local-pref, AS_PATH Length e Origin devem ser idênticos.

Local-pref

Outra opção que podemos utilizar em todos os cenários possíveis é a manipulação do atributo Local-pref. Por ser um atributo well-known e ser repassado a peers iBGP (discretionary), deve ser reconhecido por todas implementações BGP — e nos garante um comportamento bem determinístico pelo fato de a comparação da Local-pref ser o primeiro passo no algoritmo de seleção do BGP. Isso quer dizer que mesmo anúncios onde o AS_PATH é maior ainda pode ser preferido utilizando o Local-pref.

Acima vemos o atributo sendo modificado ao recebermos o anúncio no CE-A, e sendo repassado internamente. Aqui, como temos apenas um router na borda, repassar este atributo internamente não nos trará nenhum beneficio. Porem, com mais de uma saída para o mundo, repassar o atributo internamente nos dará mais flexibilidade para influenciar o roteamento interno.

CE-A:ip prefix-list PE-A-PREF-150 permit 172.16.10.0/24
ip prefix-list PE-B-PREF-150 permit 172.16.20.0/24
!
route-map LINK-A permit 10
match ip address prefix-list PE-A-PREF-150
set local-pref 150
!
route-map LINK-B permit 10
match ip address prefix-list PE-B-PREF-150
set local-pref 150
!
routeer bgp 65000
neighbor PE-A route-map LINK-A in
neighbor PE-B route-map LINK-B in
!
ou
set policy-options prefix-list PE-A-PREF-150 172.16.10.0/24
set policy-options prefix-list PE-A-PREF-150 172.16.20.0/24
!
set policy-options policy-statement LINK-A term PE-A-PREF-150 from prefix-list PE-A-PREF-150
set policy-options policy-statement LINK-A term PE-A-PREF-150 then local-preference 150
set policy-options policy-statement LINK-A term PE-A-PREF-150 then accept
!
set policy-options policy-statement LINK-B term PE-B-PREF-150 from prefix-list PE-B-PREF-150
set policy-options policy-statement LINK-B term PE-B-PREF-150 then local-preference 150
set policy-options policy-statement LINK-B term PE-B-PREF-150 then accept
!
<snip>
set protocols bgp group AS3356 neighbor PE-A import LINK-A
set protocols bgp group AS2914 neighbor PE-B import LINK-B
!

Load sharing (BGP Multipath)

Caso o objetivo seja utilizar ambos os links, é possível fazer com que o tráfego seja “balanceado” através de preferir diferentes prefixos em cada uplink. No entanto, algumas vezes temos a necessidade de instalar dois anúncios para o mesmo prefixo na tabela, e fazer o balanceamento via FIB hashing. Para instalar as duas rotas na RIB, precisamos ter mais de um neighbor — ou seja, esta técnica pode ser usada tanto em uma conexão com apenas um router na borda (dual homed/single multi homed) quanto internamente (nos gateways internos caso tenhamos iBGP).

Uma coisa que temos que nos atentar é que prefixos so são marcados como multipath (por default) se os seguintes atributos forem idênticos:

  • Weight
  • Local Preference
  • AS Path (AS-PATH Length idêntico e mesmo next-hop ASN)
  • Origin code
  • MED
  • IGP metric

Isso significa que, se quisermos trabalhar com multipath na topologia multihomed (mais de um AS upstream), devemos utilizar a feature “bestpath as-path multipath-relax” (Cisco) ou “multipath multiple-as” (Junos).

Vale lembrar que o multipath vai ter efeito apenas onde recebemos mais de um prefixo: em outras palavras, podemos fazer multipath na borda (caso tenhamos mais de um uplink no router de borda) ou no gateway interno (caso tenhamos mais de um ponto de saída no AS)

CE-A:ip prefix-list DEFAULT-PE-A permit 0.0.0.0/0
ip prefix-list DEFAULT-PE-B permit 0.0.0.0/0
!
route-map LINK-A permit 10
match ip address prefix-list DEFAULT-PE-A
!
route-map LINK-A deny 99
!
route-map LINK-B permit 10
match ip address prefix-list DEFAULT-PE-B
!
route-map LINK-B deny 99
!
router bgp 65000
bgp bestpath as-path multipath-relax
neighbor PE-A route-map LINK-A in
neighbor PE-B route-map LINK-B in
!
maximum-paths 2
!
Gateway Interno:ip prefix-list DEFAULT-ONLY permit 0.0.0.0/0
!
route-map DEFAULT-ONLY permit 10
match ip address prefix-list DEFAULT-ONLY
!
route-map DEFAULT-ONLY deny 99
!
router bgp 65000
bgp bestpath as-path multipath-relax
neighbor CE-A route-map DEFAULT-ONLY in
neighbor CE-B route-map DEFAULT-ONLY in
!
maximum-paths 2
!

Manipulando a entrada do tráfego: Ingress

No sentido contrario, para manipular a forma como o tráfego entra no nosso AS, precisamos influenciar o processo de decisão do(s) AS(es) vizinho(s). Sendo assim, muitos elementos estão fora do nosso controle — e os atributos que podemos manipular são apenas aqueles que são anunciados em uma sessão eBGP e tem algum efeito no processo de decisão: AS_PATH, Origin e MED.

Origin

O codigo Origin é um atributo “Well-known” e “mandatory” — ou seja, sempre é propagado nos anúncios BGP (eBGP e iBGP). Possui apenas 3 valores validos: “e” “i” ou “?”. Este atributo historicamente indicava a maneira como o prefixo foi injetado no BGP: “e” — EGP, “i” — IGP, “?” — incomplete. A maneira de como o prefixo é originado no BGP pode influenciar no valor deste atributo. Caso tenhamos apenas um AS upstream, o Origin code pode ser utilizado efetivamente para manipular o trafego.

No exemplo, iremos fazer com que todo o trafego ingress utilize o link A, fazendo com que o anúncio do prefixo 192.0.2.0/24 com origin IGP seja o melhor anúncio dentro do nosso upstream (AS 2914) — resultando no ponto de saída através do PE-A como best.

CE-A:ip prefix-list TO-PE-A permit 192.0.2.0/24
ip prefix-list TO-PE-B permit 192.0.2.0/24
!
route-map LINK-A permit 10
match ip address prefix-list TO-PE-A
set origin igp
!
route-map LINK-A deny 99
!
route-map LINK-B permit 10
match ip address prefix-list TO-PE-B
set origin incomplete
!
route-map LINK-B deny 99
!
!
router bgp 65000
neighbor PE-A route-map LINK-A out
neighbor PE-B route-map LINK-B out
!

MED

Já falamos um pouco sobre a MED ali em cima. No caso da manipulação do tráfego no sentido ingress, temos que lembrar que este atributo não necessariamente é repassado a neighbors BGP — podendo ser removido ou alterado ao longo do caminho. Sendo assim, seu uso é normalmente visto em cenários dual homed — onde precisamos apenas influenciar a decisão do próximo AS para indicar qual o melhor/pior ponto de entrada para nosso AS local.

De uma forma similar ao exemplo anterior, agora manipularemos a MED para sinalizar qual prefixo sera o “melhor” para o nosso upstream, também utilizando o link A como principal para o prefixo 192.0.2.0/24.

CE-A:ip prefix-list TO-PE-A permit 192.0.2.0/24
ip prefix-list TO-PE-B permit 192.0.2.0/24
!
route-map LINK-A permit 10
match ip address prefix-list TO-PE-A
set metric 100
!
route-map LINK-A deny 99
!
route-map LINK-B permit 10
match ip address prefix-list TO-PE-B
set metric 150
!
route-map LINK-B deny 99
!
!
router bgp 65000
neighbor PE-A route-map LINK-A out
neighbor PE-B route-map LINK-B out
!

AS_PATH Length

O tamanho do atributo AS_PATH indica o caminho por onde um determinado prefixo see propaga. Logo, o tamanho do atributo AS_PATH significa a quantidade de ASes um determinado pacote deve cruzar ate chegar ao seu destino. O BGP, conhecido como um protocolo “Path Vector” utiliza este atributo não só para decidir o melhor caminho, mas também para decidir se um prefixo deve ser recebido (prevenção de loops) ou anunciado a um peer (advertise-peer-as).

Como este atributo deve estar presente em todo anuncio BGP, podemos manipular o tamanho do atributo por meio de uma técnica conhecida como AS-PATH Prepending. Ao fazermos o prepending no anuncio, esta mudança terá um efeito global, isto é, a mudança vai ser refletida em todas as partes da internet por onde o prefixo é propagado. Neste exemplo abaixo, utilizando a ferramenta RIPE Stat API, podemos ver o efeito prepending em um dos prefixos 8.8.8.0/24:

{
origin: "IGP",
last_updated: "2019-08-20T05:26:51",
as_path: "25091 15169 15169 15169",
community: "25091:21403 65300:15169",
asn_origin: "15169",
prefix: "8.8.8.0/24",
next_hop: "195.208.209.93",
peer: "195.208.209.93"
},

Neste exemplo, iremos fazer um prepend de 2 para o AS 3257. Com este método, conseguimos fazer com que o trafego que venha do AS 3356 ainda nos alcance pelo link A (upstream AS 2914), mesmo estando conectado diretamente ao nosso outro upstream (AS 3257).

CE-A:ip prefix-list PE-A permit 192.0.2.0/24
!
route-map LINK-A permit 10
match ip address prefix-list PE-A
!
route-map LINK-A deny 99
!
router bgp 65000
neighbor PE-A route-map LINK-A out
!
CE-B:set policy-options prefix-list PE-B 192.0.2.0/24
!
set policy-options policy-statement LINK-B term PREPEND-2 from prefix-list PE-B
set policy-options policy-statement LINK-B term PREPEND-2 then as-path-prepend "65000 65000"
set policy-options policy-statement LINK-B term PREPEND-2 then accept
!
set policy-options policy-statement LINK-B term reject then reject
!
<snip>
set protocols bgp group AS3257 neighbor PE-B export LINK-B
!

Longest-match

Por fim, caso tenhamos mais de um prefixo, ou um bloco maior (isso e, um /23, /22, etc), podemos manipular os anúncios ao(s) nosso(s) upstream fazendo com que determinados “sub-blocos” sejam anunciados juntos ao bloco agregado, influenciando a decisão de roteamento dos nossos vizinhos através da logica “longest match”. Em outras palavras, podemos anunciar um determinado /24 junto ao seu agregado em cada sessão upstream de forma alternada. Isso nos garantira que o tráfego com destino a uma determinada parte do bloco utilize sempre tal sessão, e ao mesmo tempo, garantindo a disponibilidade de todos os blocos caso o link principal esteja indisponível.

No exemplo acima, podemos anunciar dois prefixos de cada CE: Um referente ao bloco (o agregado — /16, popularmente falando) e um especifico (o /24). Desta forma, o tráfego com destino ao prefixo 172.16.10.0/24 utilizará o link A como entrada (upstream AS 2914), e o tráfego para 172.16.20.0/24 irá chegar pelo AS 3257 (link B). Caso algum dos dois anúncios ou link esteja indisponível, o prefixo /16 atrai todo o tráfego destinado ao anúncio que foi afetado/está ausente na internet.

CE-A:ip prefix-list SPECIFIC permit 172.16.10.0/24
ip prefix-list AGGREGATE permit 172.16.0.0/16
!
route-map LINK-A permit 10
match ip address prefix-list SPECIFIC
!
route-map LINK-A permit 20
match ip address prefix-list AGGREGATE
!
router bgp 65000
neighbor PE-A route-map LINK-A out
!
CE-B:set policy-options prefix-list SPECIFIC 172.16.20.0/24
set policy-options prefix-list AGGREGATE 172.16.0.0/16
!
set policy-options policy-statement LINK-B term SPECIFIC from prefix-list SPECIFIC
set policy-options policy-statement LINK-B term SPECIFIC then accept
!
set policy-options policy-statement LINK-B term AGGREGATE from prefix-list AGGREGATE
set policy-options policy-statement LINK-B term AGGREGATE then accept
!
<snip>
set protocols bgp group AS3257 neighbor PE-B export LINK-B
!

Nota: vale lembrar que a maioria dos provedores não aceita anúncios mais específicos que /24. Se for o caso de o provedor aceitar algum prefixo mais longo (/25, /26, ou ate /32), não é garantido que este anuncio seja propagado para toda a internet. A recomendação atual é sempre trabalhar com prefixos /24 ou menos específicos.

Conclusão

Para nos ajudar a otimizar o uso de recursos de network, podemos nos utilizar da manipulação dos atributos BGP — ferramentas que são de extrema utilidade para podermos operar uma rede conectada nessa ̶b̶a̶g̶u̶n̶ç̶a̶ internet muito doida. No post de hoje falamos como podemos manipular a entrada e saída de tráfego de um determinado AS, e em quais cenários tais práticas podem ser aplicadas.

Se gostou do conteúdo, peço para compartilhar com outros do ramo. Não se esqueça de seguir a mim e ao TechRebels clicando follow aí embaixo :)

Sobre o autor:

Bernardo, CCIE #57862

Cloud Network Engineer

linkedin.com/in/bernardosoares/

--

--