Planet Collab

🔒
❌ About FreshRSS
There are new articles available, click to refresh the page.
Today — July 23rd 2021Your RSS feeds

RFC 9075: Report from the IAB COVID-19 Network Impacts Workshop 2020

La pandémie de Covid-19 en 2020 a affecté de nombreux aspects de notre vie. Concernant plus spécifiquement l'Internet, elle a accru l'utilisation d'outils de communication informatiques. Quels ont été les effets de ces changements sur l'Internet ? Un atelier de l'IAB fait le point sur ces effets et en tire des leçons. Je vous le dis tout de suite : contrairement à certains discours sensationnalistes, l'Internet n'a pas subi de conséquences sérieuses.

De janvier Ă  mars 2020, de nombreux pays ont imposĂ© un confinement plus ou moins strict. Des activitĂ©s comme le travail ou l'Ă©ducation devaient se faire Ă  distance, en utilisant les outils numĂ©riques. Certains politiciens ont tenu des discours dramatisants, prĂ©tendant que, si on ne renonçait pas Ă  regarder ses vidĂ©os favorites, l'Internet allait s'Ă©crouler. MĂȘme si aucun professionnel des rĂ©seaux n'a repris ce discours, cela ne veut pas dire qu'il ne s'est rien passĂ©. L'IAB a donc organisĂ© en novembre 2020 un atelier (Ă©videmment tenu en ligne car il n'y avait pas le choix) pour Ă©tudier les effets de ces confinements sur l'Internet, comprendre ce qui est arrivĂ© et peut-ĂȘtre formuler des recommandations.

Donc, pendant le confinement et l'augmentation du tĂ©lĂ©travail qui en a rĂ©sultĂ©, le trafic Internet a changĂ©. Il n'a pas toujours augmentĂ© (les travailleurs utilisaient Ă©galement Internet quand ils Ă©taient au bureau, et les gens regardaient dĂ©jĂ  Netflix avant la pandĂ©mie) mais il s'est dĂ©placé : trafic de type diffĂ©rent, Ă  des heures diffĂ©rentes, etc. Et, dans la plupart des pays, c'est arrivĂ© assez soudainement, laissant peu de temps pour l'adaptation. La sĂ©curitĂ© a Ă©tĂ© Ă©galement trĂšs affectĂ©e, les mesures de sĂ©curitĂ© conçues sur la base d'un lieu physique n'ayant plus de sens. Tout Ă  coup, il a fallu autoriser beaucoup d'accĂšs distants, avec tous les risques que cela impliquait. L'atelier lui-mĂȘme a Ă©tĂ© diffĂ©rent des prĂ©cĂ©dents ateliers de l'IAB, qui Ă©taient fondĂ©s sur une participation physique pendant deux jours continus. Cette fois, l'atelier s'est fait en trois sessions Ă  distance, avec respiration et rĂ©flexion entre les sessions.

Qu'ont observĂ© les acteurs de l'Internet ? À l'atelier, certains FAI ou gĂ©rants de points d'Ă©change Internet ont signalĂ© des accroissements de 20 % du trafic. C'est Ă  la fois beaucoup et peu. C'est beaucoup car c'est survenu soudainement, sans ĂȘtre Ă©talĂ© sur une pĂ©riode permettant le dĂ©ploiement de nouvelles ressources, et c'est peu, car la croissance de l'utilisation des rĂ©seaux est un phĂ©nomĂšne permanent : il faut toujours augmenter la capacitĂ© (20 % reprĂ©sente une augmentation annuelle typique, mais qui fut concentrĂ©e en quelques semaines). On voit ici le trafic sur le point d'Ă©change Internet de Francfort (la source est ici). S'il y a bien une brusque montĂ©e dĂ©but 2020 avec le dĂ©marrage du confinement, il faut noter qu'elle s'inscrit dans une augmentation du trafic Internet sur le long terme :

Cette montée du trafic lors du confinement est également relativisée sur les statistiques de trafic au point d'échange parisien (la source est ici) :

De mĂȘme, l'article « Measurement of congestion on ISP interconnection links » mesure des moments de congestion limitĂ©s aux États-Unis en mars. Cette croissance Ă©tait trĂšs inĂ©galement rĂ©partie selon les services. Vous ne serez pas surpris d'apprendre que certains opĂ©rateurs de services de vidĂ©o-confĂ©rence ont vu leur activitĂ© tripler, voire dĂ©cupler. Une intĂ©ressante conclusion est que, contrairement Ă  ce que certains discours sensationnalistes comme ceux de Thierry Breton prĂ©tendaient, l'Internet n'a pas connu de problĂšme gĂ©nĂ©ralisĂ©. Comme toujours dans ce rĂ©seau mondial, les problĂšmes sont restĂ©s localisĂ©s, ralentissements Ă  certains endroits, baisse automatique de la qualitĂ© des vidĂ©os Ă  d'autres, mais pas de problĂšme systĂ©mique. Ce bon rĂ©sultat n'a pas Ă©tĂ© obtenu uniquement par la capacitĂ© du rĂ©seau existant Ă  encaisser la montĂ©e en charge. Il y a eu Ă©galement de nombreuses actions prises par les diffĂ©rents acteurs du rĂ©seau, qui ne sont pas restĂ©s les bras croisĂ©s face au risque. Bref, vu du point de vue scientifique, c'Ă©tait une expĂ©rience intĂ©ressante, qui montre que l'Internet peut rĂ©sister Ă  des crises, ce qui permet de penser que les problĂšmes futurs ne seront pas forcĂ©ment fatals.

[L'atelier portait bien sur l'Internet, sur l'infrastructure, pas sur les services hĂ©bergĂ©s. Il est important de faire la distinction car certains services (comme ceux de l'Éducation Nationale en France) ont Ă©tĂ© incapables de rĂ©sister Ă  la charge et se sont vite Ă©croulĂ©s. Mais ce n'Ă©tait pas une dĂ©faillance de l'Internet, et renoncer Ă  regarder des vidĂ©os n'aurait pas protĂ©gĂ© le CNED contre ces problĂšmes. Notons qu'il n'y avait pas de fatalitĂ© Ă  ces problĂšmes des services : WikipĂ©dia et Pornhub, deux services trĂšs diffĂ©rents dans leur utilisation et leur gestion, ont continuĂ© Ă  fonctionner correctement.]

Voyons maintenant les détails, dans la section 3 du RFC. On commence avec la sous-section 3.1, les mesures. Que s'est-il passé ? Comme on pouvait s'y attendre, le trafic résidentiel a augmenté (en raison du travail à la maison), tandis que celui des réseaux mobiles chutait (on se déplaçait moins). Le trafic vers les opérateurs de services de vidéo-conférence (comme Zoom) a augmenté, ainsi que celui des services de distraction (VoD) pendant la journée. Mais il y a eu surtout un gros déplacement des pics d'activité. En semaine, l'activité Internet était trÚs liée au rythme de la journée, avec des trafics trÚs différents dans la journée et le soir. Pendant les confinements, on a vu au contraire une activité plus étalée dans le temps chez les FAI résidentiels, et une activité de la semaine qui ressemble à celle des week-ends. Là encore, pas de conséquences graves, bien que certains FAI aient signalé des ralentissements notamment en mars 2020. Bref, l'Internet sait bien résister aux sautes de trafic qui, il est vrai, font partie de son quotidien depuis sa création.

Parmi les articles soumis pour l'atelier, je vous recommande, sur la question des mesures, le trÚs détaillé « A view of Internet Traffic Shifts at ISP and IXPs during the COVID-19 Pandemic ». Les auteurs ont observé le trafic chez plusieurs opérateurs et points d'échange (le seul nommé est le réseau académique de Madrid). Par exemple, en utilisant diverses heuristiques (le port seul ne suffit plus, tout le monde étant sur 443), les auteurs ont des chiffres concernant diverses applications (vidéo-conférence, vidéo à la demande, jeux en ligne, etc). Moins détaillé, il y a le « IAB COVID-19 Workshop: Interconnection Changes in the United States » (à l'origine publié dans un Internet-Draft, draft-feamster-livingood-iab-covid19-workshop).

Un exemple de changement du trafic est donné par le Politecnico de Turin qui a vu son trafic sortant multiplié par 2,5, en raison de la diffusion de ses 600 cours en ligne par jour, alors que le trafic entrant était divisé par 10. Dans les universités, le trafic entrant est typiquement bien plus gros que le sortant (les étudiants et enseignants sont sur le campus et accÚdent à des ressources distantes) mais cela a changé pendant le confinement, les ressources externes étant accédées depuis la maison. (Une entreprise aurait pu voir des effets différents, si les employés accÚdent à ces ressources externes via le VPN de l'entreprise.) Le REN REDIMadrid a vu également de gros changements dans son trafic. Effet imprévu, les communications avec les AS d'Amérique latine a augmenté, probablement parce que les étudiants hispanophones américains profitaient des possibilités de cours à distance pour suivre les activités des universités de l'ex-métropole.

Comme dit plus haut, les rĂ©seaux mobiles, 4G et autres, ont vu leur activitĂ© baisser. L'article « A Characterization of the COVID-19 Pandemic Impact on a Mobile Network Operator Traffic » note une mobilitĂ© divisĂ©e par deux en Grande-Bretagne et un trafic diminuĂ© d'un quart. (Certaines personnes ne sont plus mobiles mais utilisent la 4G Ă  la maison, et il y a bien d'autres phĂ©nomĂšnes qui rendent compliquĂ©e l'analyse.) L'observation des signaux envoyĂ©s par les tĂ©lĂ©phones (le rĂ©seau mobile sait oĂč vous ĂȘtes
) a Ă©galement permis de mesurer l'ampleur de la fuite hors des grandes villes (10 % des londoniens).

Et dans la connexion des FAI avec les services sur le cloud ? Les liens d'interconnexion entre FAI et fournisseurs de services ont-ils tenu ? Pas de congestion persistante mais des moments de tension, par exemple aux États-Unis vers les petits FAI, qui n'avaient pas toujours une interconnexion suffisante pour encaisser tout le trafic accru. Comme toujours sur l'Internet, malgrĂ© le caractĂšre mondial de la pandĂ©mie, il y a peu d'observations valables partout et tout le temps, vu la variĂ©tĂ© des capacitĂ©s des liaisons. MalgrĂ© l'observation gĂ©nĂ©rale « globalement, ça a tenu », il y a toujours des endroits oĂč ca rame Ă  certains moments.

En effet, le bon fonctionnement de l'Internet mondial ne signifiait pas que tous les M. Toutlemonde de la Terre avaient une bonne qualitĂ© de connexion. L'article « The Impact of COVID-19 on Last-mile Latency » (plus de dĂ©tails sur le blog de l'auteur) rend compte de mesures faites avec les sondes RIPE Atlas, qui trouvent une congestion plus frĂ©quente sur le « premier kilomĂštre » (le lien entre la maison de M. Toutlemonde et le premier POP de son FAI) pendant le confinement). Cela dĂ©pend Ă©videmment beaucoup du FAI et du pays, le Japon ayant Ă©tĂ© particuliĂšrement touchĂ©. La situation s'est toutefois amĂ©liorĂ©e au fur et Ă  mesure, notamment en raison des dĂ©ploiements de capacitĂ© supplĂ©mentaire par les opĂ©rateurs (et, au Japon, des investissements qui Ă©taient prĂ©vus pour les Jeux Olympiques). L'Internet se retrouve donc plus robuste qu'avant. Le RFC cite mĂȘme Nietzsche « Ce qui ne me tue pas me rend plus fort ».

On l'a dit, le trafic n'a pas seulement changé quantitativement mais aussi qualitativement. La vidéo-conférence a, fort logiquement, crû. Le trafic trÚs asymétrique de certains FAI grand public (beaucoup plus de trafic entrant vers les consommateurs que de trafic sortant) s'est un peu égalisé, en raison des flux vidéos sortants. NCTA et Comcast signalent plus de 30 % de hausse de ce trafic sortant, Vodafone 100 %. Un rapport d'Ericsson sur les utilisateurs signale :

  • Une augmentation de l'utilisation de l'Internet par 9 utilisateurs sur 10 (le dixiĂšme Ă©tait peut-ĂȘtre dĂ©jĂ  connectĂ© tout le temps ?) et des usages nouveaux par 1 utilisateur sur 5 (des gens comme moi qui se mettent Ă  la vidĂ©o-confĂ©rence alors qu'ils dĂ©testaient cela avant).
  • Peu de plaintes concernant les performances.
  • Évidemment un changement dans les applications utilisĂ©es, les applications de vidĂ©o-confĂ©rence voient leur usage s'accroitre, celles liĂ©es Ă  la location d'hĂŽtels ou de restaurants (ou, note le RFC, celles permettant la recherche d'une place de parking) le voient diminuer.
Ces changements sont-ils permanents ? Resteront-ils dans le « monde d'aprĂšs » ? Le RFC estime que le tĂ©lĂ©travail s'est dĂ©sormais installĂ© et restera ; on peut donc prĂ©voir que l'utilisation intensive d'outils de rĂ©union Ă  distance persistera (cf. le rapport « Work-At-Home After Covid-19—Our Forecast »).

AprĂšs ces observations, la section 3 du RFC continue avec des considĂ©rations sur les problĂšmes opĂ©rationnels constatĂ©s. D'abord, un point de fracture numĂ©rique. Aux États-Unis, et probablement dans bien d'autres pays, le dĂ©bit entrant chez les utilisateurs est corrĂ©lĂ© au niveau de vie. Mais on a constatĂ© pendant la pandĂ©mie une rĂ©duction de l'Ă©cart entre riches et pauvres (l'Ă©tude ne portait pas sur des foyers individuels mais sur des zones gĂ©ographiques identifiĂ©es par leur code postal, un bon indicateur de niveau de vie, au moins aux USA). Cette rĂ©duction de l'Ă©cart n'Ă©tait pas forcĂ©ment liĂ©e Ă  un changement de comportement des utilisateurs mais l'Ă©tait peut-ĂȘtre au fait que certains FAI comme Comcast ont Ă©tendu la capacitĂ© liĂ©e Ă  des abonnements bon marchĂ©, par souci de RSE pendant la crise. L'Ă©cart entre riches et pauvres Ă©tait donc peut-ĂȘtre dĂ» Ă  une diffĂ©rence dans les abonnements souscrits, pas Ă  une diffĂ©rence d'utilisation de l'Internet.

Les applications vedettes des confinements ont évidemment été les outils de réunion en ligne, gros services privateurs et capteurs de données personnelles comme Microsoft Teams ou Zoom, ou bien services reposant sur des logiciels libres comme BigBlueButton (dont le RFC, qui reflÚte un point de vue surtout étatsunien, ne parle pas). D'autres outils de distribution de vidéo, comme YouTube ont vu également leur trafic augmenter soudainement. Certains acteurs, comme justement YouTube, ont délibérement réduit la qualité des vidéos pour diminuer la charge sur le réseau, mais il n'est pas évident que cela ait eu un effet majeur. Autre catégorie d'applications qui a vu son utilisation augmenter, les jeux en ligne. Souvent trÚs consommateurs de ressources, ils ont la particularité de demander à la fois une forte capacité (en raisons des contenus multimédias riches à télécharger) et une faible latence (quand on tire sur le zombie, il doit tomber tout de suite). La mise à jour d'un jeu trÚs populaire a un effet trÚs net sur le réseau des FAI ! Mais il faut noter que ce n'est pas un phénomÚne spécifique au confinement. Les opérateurs ont déjà dû faire face à des évÚnements soudains, comme une nouvelle version d'un logiciel trÚs utilisé ou comme une nouvelle mode, par exemple une application qui connait un succÚs rapide, ce qui est assez fréquent sur l'Internet. Outre ces « effets Slashdot », il y a aussi les attaques par déni de service, qui nécessitent de suravitailler (mettre davantage de capacité que strictement nécessaire). Les opérateurs ont donc déjà de l'expérience dans ce domaine mais, note le RFC, cette expérience n'est pas toujours partagée.

Une discussion lors de l'atelier a porté sur la possibilité de gérer ce genre de problÚmes par des mesures discriminatoires, de type qualité de service (un terme propagandiste, il faut le noter : si on discrimine, certains auront une meilleure qualité et d'autres une moins bonne). Marquer le trafic « pas essentiel » (qui décidera de ce qui n'est pas essentiel ?) avec DSCP pour le faire passer par les chemins les plus lents aurait-il aidé ? Compte-tenu du caractÚre trÚs brûlant de ce débat, il n'est pas étonnant qu'aucun consensus n'est émergé de l'atelier. Le RFC se réjouit qu'au moins les engueulades ont été moins graves que d'habitude.

Une bonne partie de cet atelier Ă©tait consacrĂ© Ă  l'Ă©tude de faits : qu'ont vu les opĂ©rateurs ? Or, ils n'ont pas vu la mĂȘme chose. Cela reflĂšte les diffĂ©rences de situation mais aussi les diffĂ©rences dans les outils d'observation. La mĂ©trologie n'est pas une chose facile ! Par exemple, les applications de vidĂ©o-confĂ©rence ou de distribution de vidĂ©o Ă  la demande ont des mĂ©canismes de correction d'erreur et de gestion de la pĂ©nurie trĂšs Ă©laborĂ©s. L'application s'adapte en permanence aux caractĂ©ristiques du rĂ©seau, par exemple en ajustant son taux de compression. C'est trĂšs bien pour l'utilisateur, cela permet de lui dissimuler une grande partie des problĂšmes, mais cela complique l'observation. Et quand il y a un problĂšme, il est difficile Ă  analyser. L'autre jour, sans que cela ait de rapport avec un confinement, je regardais une vidĂ©o sur Netflix et la qualitĂ© de l'image Ă©tait vraiment mĂ©diocre, gĂąchant le plaisir. Mais oĂč Ă©tait le problĂšme ? Mon PC Ă©tait trop lent ? Le Wifi Ă©tait pourri ? Le rĂ©seau de Free surchargé ? L'interconnexion entre Free et Netflix Ă©tait-elle encombrĂ©e ? Les serveurs de Netflix ramaient-ils ? C'est trĂšs difficile Ă  dire, et cela dĂ©pend de beaucoup de choses (par exemple, deux utilisateurs de Netflix ne tombent pas forcĂ©ment sur le mĂȘme serveur chez Netflix et peuvent donc avoir des vĂ©cus diffĂ©rents). Et puis, globalement, on manque de capacitĂ©s d'observation sur l'Internet. Le client ne voit pas ce qui se passe sur le serveur, le serveur ne sait pas grand'chose sur le client, et peut-ĂȘtre qu'aucun des deux n'a pas visibilitĂ© sur l'interconnexion. Chacun connait bien son rĂ©seau, mais personne ne connait l'Internet dans son ensemble. Le RFC note que, paradoxalement, la Covid-19 a amĂ©liorĂ© les choses, en augmentant le niveau de coopĂ©ration entre les acteurs de l'Internet.

Et la sĂ©curité ? Elle a aussi Ă©tĂ© discutĂ©e Ă  l'atelier car le passage brusque de tant de gens au tĂ©lĂ©travail a changĂ© le paysage de la sĂ©curitĂ©. On ne pouvait plus compter sur le pare-feu corporate et sur les machines du bureau soigneusement verrouillĂ©es par la DSI. Au lieu de cela, tout le monde utilisait des VPN pas toujours bien maitrisĂ©s (cf. l'article « IAB COVID-19 Network Impacts »). Et la pandĂ©mie a Ă©tĂ© l'occasion de nombreuses escroqueries (dĂ©crites dans le mĂȘme article). À propos de sĂ©curitĂ©, le RFC en profite pour vanter les rĂ©solveurs DNS menteurs et critiquer DoH (qui n'est pour rien dans ces escroqueries).

En conclusion, le RFC note que le bon fonctionnement de l'Internet pendant la pandĂ©mie n'Ă©tait pas dĂ» uniquement Ă  ses qualitĂ©s intrinsĂšques, mais aussi Ă  l'action de nombreux acteurs. Comme d'autres professions, les techniciens et techniciennes de l'Internet Ă©taient une des lignes de dĂ©fense face Ă  l'Ă©pidĂ©mie et cette ligne Ă©tait trĂšs motivĂ©e, et a tenu. Ces techniciennes et techniciens mĂ©ritent donc de chaudes fĂ©licitations. Mais on peut quand mĂȘme amĂ©liorer les choses :

  • En continuant Ă  Ă©tudier le fonctionnement de l'Internet. Le caractĂšre critique de l'Internet pour tant d'activitĂ©s humaines justifie qu'on continue Ă  analyser ses caractĂ©ristiques et ses faiblesses.
  • Le partage d'informations et la communication sont essentiels et doivent ĂȘtre accrus.
  • La lutte contre la fracture numĂ©rique doit se poursuivre, puisqu'en pĂ©riode de confinement, ĂȘtre coupĂ© du rĂ©seau, ou y accĂ©der dans de mauvaises conditions (accĂšs lent, matĂ©riel inadaptĂ©, manque de littĂ©ratie numĂ©rique), aggrave encore l'isolement.

Et le RFC se conclut par un bilan de cet atelier qui, contrairement aux ateliers précédents de l'IAB, a été fait entiÚrement en ligne. Les participants ont été plutÎt contents, notamment du fait que le travail à distance a permis de changer le format : au lieu de deux jours complets de discussions, l'atelier a pu se tenir en alternant des moments de discussion et du travail chez soi, pour approfondir et critiquer les discussions. Toutefois, le RFC note que cela a bien marché car la quasi-totalité des présents se connaissaient bien, étant des participants de longue date à l'IETF. Il n'est pas du tout évident que cela aurait aussi bien marché avec des gens nouveaux, le présentiel étant crucial pour créer des liens informels.

L'ensemble des articles Ă©crits par les participants Ă  l'atelier (pour participer, il fallait avoir Ă©crit un texte) est disponible en ligne (en bas de la page).

Ansible – with_items vs loop, what’s the difference?

July 23rd 2021 at 06:20

Ansible documentation recommend user to use or replace with_items with loop. So, with_items is the older way of writing Ansible playbooks and loop is the newer way of writing the playbook. For most part they are almost identical. So, what is the difference and how are they different. Let’s have look at a simple example to see the difference.

According to the documnetation:

“Ansible offers the loop, with_<lookup>, and until keywords to execute a task multiple times.” “The with_<lookup> keywords rely on Lookup Plugins – even items is a lookup.”

“The loop keyword is equivalent to with_list, and is the best choice for simple loops.”

URL: https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#playbooks-loops

with_items example

[jdoe@centos8 ansible_basics]$ cat with_items1.yml

---
- hosts: localhost
  gather_facts: false

  tasks:
    - name: A simple list loop
      debug: msg="My lucky numbers is {{ item }}"
      with_items: [1, [2, 3], 4, 'five']

Run the playbook and the result should be as shown below:

[jdoe@centos8 ansible_basics]$ ansible-playbook with_items1.yml

PLAY [localhost] ***************************************************************

TASK [A simple list loop] ******************************************************
ok: [localhost] => (item=1) => {
    "msg": "My lucky numbers is 1"
}
ok: [localhost] => (item=2) => {
    "msg": "My lucky numbers is 2"
}
ok: [localhost] => (item=3) => {
    "msg": "My lucky numbers is 3"
}
ok: [localhost] => (item=4) => {
    "msg": "My lucky numbers is 4"
}
ok: [localhost] => (item=five) => {
    "msg": "My lucky numbers is five"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

As you can see with_items flattens the list [2, 3] into a single level, and prints out each item.

now the loop example

[jdoe@centos8 ansible_basics]$ cat loop1.yml

---
- hosts: localhost
  gather_facts: false

  tasks:
    - name: A simple list loop
      debug: msg="My lucky numbers is {{ item }}"
      loop: "{{ [1, [2, 3], 4, 'five'] }}" 

[jdoe@centos8 ansible_basics]$ ansible-playbook loop1.yml

PLAY [localhost] ***************************************************************

TASK [A simple list loop] ******************************************************
ok: [localhost] => (item=1) => {
    "msg": "My lucky numbers is 1"
}
ok: [localhost] => (item=[2, 3]) => {
    "msg": "My lucky numbers is [2, 3]"
}
ok: [localhost] => (item=4) => {
    "msg": "My lucky numbers is 4"
}
ok: [localhost] => (item=five) => {
    "msg": "My lucky numbers is five"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

As you can see in the list [2, 3], loop does not flatten the list and prints the actual list. Ansible documentation recommends users to use flatten(1).

---
- hosts: localhost
  gather_facts: false

  tasks:
    - name: A simple list loop
      debug: msg="My lucky numbers is {{ item }}"
      loop: "{{ [1, [2, 3], 4, 'five'] | flatten(1) }}" 

[jdoe@centos8 ansible_basics]$ ansible-playbook loop1.yml

PLAY [localhost] ***************************************************************

TASK [A simple list loop] ******************************************************
ok: [localhost] => (item=1) => {
    "msg": "My lucky numbers is 1"
}
ok: [localhost] => (item=2) => {
    "msg": "My lucky numbers is 2"
}
ok: [localhost] => (item=3) => {
    "msg": "My lucky numbers is 3"
}
ok: [localhost] => (item=4) => {
    "msg": "My lucky numbers is 4"
}
ok: [localhost] => (item=five) => {
    "msg": "My lucky numbers is five"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Now the loop behaves like with_items.

Apply this to a real example

jdoe@centos8 ansible_basics]$ cat loop2.yml


---
- hosts: localhost
  gather_facts: false

  tasks:
    - name: A simple list loop
      debug: msg="The device IP is {{ item }}"
      loop: '{{ ["10.10.10.1", "20.20.20.2", "30.30.30.3"] | flatten(1) }}' 

[jdoe@centos8 ansible_basics]$ ansible-playbook loop2.yml

PLAY [localhost] ***************************************************************

TASK [A simple list loop] ******************************************************
ok: [localhost] => (item=10.10.10.1) => {
    "msg": "The device IP is 10.10.10.1"
}
ok: [localhost] => (item=20.20.20.2) => {
    "msg": "The device IP is 20.20.20.2"
}
ok: [localhost] => (item=30.30.30.3) => {
    "msg": "The device IP is 30.30.30.3"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Registering loop output as a variables using echo

[jdoe@centos8 ansible_basics]$ cat loop3.yml

--
- hosts: localhost
  gather_facts: false

  tasks:
    - name: Register loop output as a variable
      shell: "echo {{ item }}"
      loop: '{{ ["10.10.10.1", "20.20.20.2", "30.30.30.3"] }}'
      register: echo

[jdoe@centos8 ansible_basics]$ ansible-playbook loop3.yml

PLAY [localhost] *************************************************************************************************************************************

TASK [Register loop output as a variable] ************************************************************************************************************
changed: [localhost] => (item=10.10.10.1)
changed: [localhost] => (item=20.20.20.2)
changed: [localhost] => (item=30.30.30.3)

PLAY RECAP *******************************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Python reference note: As you know, in python, the list looks like this.

list1 = [1, [2, 3], 4, 'five']

In YAML, the list can be written in two ways.

      with_items: 
        - 1
        - [2, 3]
        - 4
        - "five"

OR

with_items: [1, [2, 3], 4, 'five']

Same for the loop example

      loop: 
        - 1
        - [2, 3]
        - 4
        - "five"

OR

      loop: "{{ [1, [2, 3], 4, 'five'] }}" 

Now you know how to loop or with_items.

Cisco IOS-XE upgrade – manual upgrade and Ansible software clean

July 22nd 2021 at 04:05

This is IOS XE upgrade test run for Ansible IOS XE upgrade development. Have to work out the manual task first for automation.

show version

csr1kv01#show ver
Cisco IOS XE Software, Version 16.08.02
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.2, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2018 by Cisco Systems, Inc.
Compiled Wed 26-Sep-18 21:50 by mcpre



Download the .bin file to device flash:

csr1kv01#dir | inc csr1000v-universalk9.16.08.03.SPA.bin
20 -rw- 419950487 Jul 5 2021 06:45:10 +00:00 csr1000v-universalk9.16.08.03.SPA.bin

Check show book, if the BOOT variable is already configured correctly, there is no need to perform the boot config change.

csr1kv01#show boot
BOOT variable does not exist
CONFIG_FILE variable does not exist
BOOTLDR variable does not exist
Configuration register is 0x2102

Note: In install mode, your boot statement must always be packages.conf in install mode.
URL: https://www.cisco.com/c/en/us/support/docs/switches/catalyst-9300-series-switches/216231-upgrade-guide-for-cisco-catalyst-9000-sw.html

Change the boot configuration per Cisco documentation

csr1kv01#show flash: | in packages.conf
7 1941 May 25 2021 14:32:04.0000000000 +00:00 /bootflash/packages.conf

csr1kv01#conf t
csr1kv01(config)#no boot sys
csr1kv01(config)#boot sys bootflash:packages.conf
csr1kv01(config)#end
csr1kv01#wri

show boot after changing the boot command

csr1kv01#show boot
BOOT variable = bootflash:packages.conf,12;
CONFIG_FILE variable does not exist
BOOTLDR variable does not exist
Configuration register is 0x2102

Run “install add [new.bin] activate commit

csr1kv01#$install add flash:csr1000v-universalk9.16.08.03.SPA.bin activate commit
install_add_activate_commit: START Thu Jul 22 01:05:11 UTC 2021
Jul 22 01:05:12.222 %INSTALL-5-INSTALL_START_INFO: R0/0: install_engine: Started install one-shot bootflash:csr1000v-universalk9.16.08.03.SPA.bin

Jul 22 01:05:12.204: %INSTALL-5-INSTALL_START_INFO: R0/0: install_engine: Started install one-shot bootflash:csr1000v-universalk9.16.08.03.SPA.bininstall_add_activate_commit: Adding PACKAGE

— Starting Add —
Performing Add on Active/Standby
[R0] Add package(s) on R0
[R0] Finished Add on R0
Checking status of Add on [R0]
Add: Passed on [R0]
Finished Add

install_add_activate_commit: Activating PACKAGE
Following packages shall be activated:
/bootflash/csr1000v-rpboot.16.08.03.SPA.pkg
/bootflash/csr1000v-mono-universalk9.16.08.03.SPA.pkg

When prompted to reload, say Yes

This operation requires a reload of the system. Do you want to proceed? [y/n]y

— Starting Activate —
Performing Activate on Active/Standby
[R0] Activate package(s) on R0
— Starting list of software package changes —
Old files list:
Removed csr1000v-mono-universalk9.16.08.02.SPA.pkg
Removed csr1000v-rpboot.16.08.02.SPA.pkg
New files list:
Added csr1000v-mono-universalk9.16.08.03.SPA.pkg
Added csr1000v-rpboot.16.08.03.SPA.pkg
Finished list of software package changes
[R0] Finished Activate on R0
Checking status of Activate on [R0]
Activate: Passed on [R0]
Finished Activate

— Starting Commit —
Performing Commit on Active/Standby

Jul 22 01:30:51.511: %INSTALL-5-INSTALL_AUTO_ABORT_TIMER_PROGRESS: R0/0: rollback_timer: Install auto abort timer will expire in 7200 seconds [R0] Commit package(s) on R0
[R0] Finished Commit on R0
Checking status of Commit on [R0]
Commit: Passed on [R0]
Finished Commit

Install will reload the system now!
SUCCESS: install_add_activate_commit Thu Jul 22 01:31:23 UTC 2021
Jul 22 01:31:23.870 %INSTALL-5-INSTALL_COMPLETED_INFO: R0/0: install_engine: Completed install one-shot PACKAGE bootflash:csr1000v-universalk9.16.08.03.SPA.bin

csr1kv01#
Jul 22 01:31:23.854: %INSTALL-5-INSTALL_COMPLETED_INFO: R0/0: install_engine: Completed install one-shot PACKAGE bootflash:csr1000v-universalk9.16.08.03.SPA.bin

Log back into your IOS XE device and check the version

login as: jdoe
Keyboard-interactive authentication prompts from server:
| Password: **********

csr1kv01#show ver
Cisco IOS XE Software, Version 16.08.03
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.3, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2019 by Cisco Systems, Inc.
Compiled Tue 09-Apr-19 16:36 by mcpre



csr1kv01#show install summary
[ R0 ] Installed Package(s) Information:
State (St): I – Inactive, U – Activated & Uncommitted,


Auto abort timer: inactive

csr1kv01#dir | in .pkg
12 -rw- 381461464 May 25 2021 14:32:04 +00:00 csr1000v-mono-universalk9.16.08.02.SPA.pkg
13 -rw- 38555320 May 25 2021 14:32:04 +00:00 csr1000v-rpboot.16.08.02.SPA.pkg
162563 -rw- 381440984 Jul 22 2021 01:05:52 +00:00 csr1000v-mono-universalk9.16.08.03.SPA.pkg
162564 -rw- 38607815 Jul 22 2021 01:07:03 +00:00 csr1000v-rpboot.16.08.03.SPA.pkg

Check the flash and do a clean up using an Ansible script

[jdoe@centos8 testing_dir]$ cat delete1.yml

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
    - name: Tell user which is working node
      debug: msg="Working on {{ inventory_hostname }}"

    - name: Delete unused pkgs and images
      ios_command:
        commands:
          - command: "request platform software package clean"
            prompt: ']'
            answer: 'y'
      ignore_errors: yes

Directory before running above playbook

csr1kv01#dir
Directory of bootflash:/

11 drwx 16384 May 25 2021 14:31:12 +00:00 lost+found
365761 drwx 4096 Jul 22 2021 01:32:29 +00:00 .installer
12 -rw- 381461464 May 25 2021 14:32:04 +00:00 csr1000v-mono-universalk9.16.08.02.SPA.pkg
13 -rw- 38555320 May 25 2021 14:32:04 +00:00 csr1000v-rpboot.16.08.02.SPA.pkg
23 -rw- 1941 Jul 22 2021 01:30:41 +00:00 packages.conf
422657 drwx 4096 Jun 7 2021 00:30:48 +00:00 core
243841 drwx 4096 Jul 22 2021 12:34:17 +00:00 .prst_sync
113793 drwx 4096 Jul 22 2021 01:30:53 +00:00 .rollback_timer
260097 drwx 28672 Jul 22 2021 01:42:54 +00:00 tracelogs
146305 drwx 4096 May 25 2021 03:37:35 +00:00 .dbpersist
211329 drwx 4096 May 25 2021 14:33:44 +00:00 virtual-instance
15 -rw- 30 Jul 22 2021 12:34:14 +00:00 throughput_monitor_params
16 -rw- 0 Jul 22 2021 12:34:14 +00:00 cvac.log
333249 drwx 4096 May 25 2021 14:34:26 +00:00 onep
17 -rw- 157 Jul 22 2021 12:34:28 +00:00 csrlxc-cfg.log
18 -rw- 35 May 25 2021 03:36:18 +00:00 pnp-tech-time
19 -rw- 91053 May 25 2021 03:36:19 +00:00 pnp-tech-discovery-summary
20 -rw- 419950487 Jul 5 2021 06:45:10 +00:00 csr1000v-universalk9.16.08.03.SPA.bin
162563 -rw- 381440984 Jul 22 2021 01:05:52 +00:00 csr1000v-mono-universalk9.16.08.03.SPA.pkg
162564 -rw- 38607815 Jul 22 2021 01:07:03 +00:00 csr1000v-rpboot.16.08.03.SPA.pkg
162562 -rw- 2790 Jul 22 2021 01:07:05 +00:00 csr1000v-universalk9.16.08.03.SPA.conf
22 -rw- 1941 Jul 22 2021 01:30:41 +00:00 packages.conf.00-

7897796608 bytes total (6085701632 bytes free)

Run the playbook

[jdoe@centos8 testing_dir]$ ansible-playbook software_clean.yml

PLAY [csr1kv01] ******************************************************************************************************************************************************************************************************************

TASK [INFORM USER WHAT PLAYBOOK SCOPE IS] ****************************************************************************************************************************************************************************************
ok: [csr1kv01] => {
    "msg": "This playbook will be run against csr1kv01"
}

TASK [DELETE UNUSED IMAGES] ******************************************************************************************************************************************************************************************************
ok: [csr1kv01]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
csr1kv01                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Directory after running above playbook

csr1kv01#dir
Directory of bootflash:/

11 drwx 16384 May 25 2021 14:31:12 +00:00 lost+found
365761 drwx 4096 Jul 22 2021 01:32:29 +00:00 .installer
23 -rw- 1941 Jul 22 2021 01:30:41 +00:00 packages.conf
422657 drwx 4096 Jun 7 2021 00:30:48 +00:00 core
243841 drwx 4096 Jul 22 2021 12:34:17 +00:00 .prst_sync
113793 drwx 4096 Jul 22 2021 01:30:53 +00:00 .rollback_timer
260097 drwx 28672 Jul 22 2021 01:42:54 +00:00 tracelogs
146305 drwx 4096 May 25 2021 03:37:35 +00:00 .dbpersist
211329 drwx 4096 May 25 2021 14:33:44 +00:00 virtual-instance
15 -rw- 30 Jul 22 2021 12:34:14 +00:00 throughput_monitor_params
16 -rw- 0 Jul 22 2021 12:34:14 +00:00 cvac.log
333249 drwx 4096 May 25 2021 14:34:26 +00:00 onep
17 -rw- 157 Jul 22 2021 12:34:28 +00:00 csrlxc-cfg.log
18 -rw- 35 May 25 2021 03:36:18 +00:00 pnp-tech-time
19 -rw- 91053 May 25 2021 03:36:19 +00:00 pnp-tech-discovery-summary
162563 -rw- 381440984 Jul 22 2021 01:05:52 +00:00 csr1000v-mono-universalk9.16.08.03.SPA.pkg
162564 -rw- 38607815 Jul 22 2021 01:07:03 +00:00 csr1000v-rpboot.16.08.03.SPA.pkg

7897796608 bytes total (6926520320 bytes free)

italchemy

Yesterday — July 22nd 2021Your RSS feeds

Cisco IOS-XE upgrade – manual upgrade and Ansible software clean

July 22nd 2021 at 04:05

This is IOS XE upgrade test run for Ansible IOS XE upgrade development. Have to work out the manual task first for automation.

show version

csr1kv01#show ver
Cisco IOS XE Software, Version 16.08.02
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.2, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2018 by Cisco Systems, Inc.
Compiled Wed 26-Sep-18 21:50 by mcpre



Download the .bin file to device flash:

csr1kv01#dir | inc csr1000v-universalk9.16.08.03.SPA.bin
20 -rw- 419950487 Jul 5 2021 06:45:10 +00:00 csr1000v-universalk9.16.08.03.SPA.bin

Check show book, if the BOOT variable is already configured correctly, there is no need to perform the boot config change.

csr1kv01#show boot
BOOT variable does not exist
CONFIG_FILE variable does not exist
BOOTLDR variable does not exist
Configuration register is 0x2102

Note: In install mode, your boot statement must always be packages.conf in install mode.
URL: https://www.cisco.com/c/en/us/support/docs/switches/catalyst-9300-series-switches/216231-upgrade-guide-for-cisco-catalyst-9000-sw.html

Change the boot configuration per Cisco documentation

csr1kv01#show flash: | in packages.conf
7 1941 May 25 2021 14:32:04.0000000000 +00:00 /bootflash/packages.conf

csr1kv01#conf t
csr1kv01(config)#no boot sys
csr1kv01(config)#boot sys bootflash:packages.conf
csr1kv01(config)#end
csr1kv01#wri

show boot after changing the boot command

csr1kv01#show boot
BOOT variable = bootflash:packages.conf,12;
CONFIG_FILE variable does not exist
BOOTLDR variable does not exist
Configuration register is 0x2102

Run “install add [new.bin] activate commit

csr1kv01#$install add flash:csr1000v-universalk9.16.08.03.SPA.bin activate commit
install_add_activate_commit: START Thu Jul 22 01:05:11 UTC 2021
Jul 22 01:05:12.222 %INSTALL-5-INSTALL_START_INFO: R0/0: install_engine: Started install one-shot bootflash:csr1000v-universalk9.16.08.03.SPA.bin

Jul 22 01:05:12.204: %INSTALL-5-INSTALL_START_INFO: R0/0: install_engine: Started install one-shot bootflash:csr1000v-universalk9.16.08.03.SPA.bininstall_add_activate_commit: Adding PACKAGE

— Starting Add —
Performing Add on Active/Standby
[R0] Add package(s) on R0
[R0] Finished Add on R0
Checking status of Add on [R0]
Add: Passed on [R0]
Finished Add

install_add_activate_commit: Activating PACKAGE
Following packages shall be activated:
/bootflash/csr1000v-rpboot.16.08.03.SPA.pkg
/bootflash/csr1000v-mono-universalk9.16.08.03.SPA.pkg

When prompted to reload, say Yes

This operation requires a reload of the system. Do you want to proceed? [y/n]y

— Starting Activate —
Performing Activate on Active/Standby
[R0] Activate package(s) on R0
— Starting list of software package changes —
Old files list:
Removed csr1000v-mono-universalk9.16.08.02.SPA.pkg
Removed csr1000v-rpboot.16.08.02.SPA.pkg
New files list:
Added csr1000v-mono-universalk9.16.08.03.SPA.pkg
Added csr1000v-rpboot.16.08.03.SPA.pkg
Finished list of software package changes
[R0] Finished Activate on R0
Checking status of Activate on [R0]
Activate: Passed on [R0]
Finished Activate

— Starting Commit —
Performing Commit on Active/Standby

Jul 22 01:30:51.511: %INSTALL-5-INSTALL_AUTO_ABORT_TIMER_PROGRESS: R0/0: rollback_timer: Install auto abort timer will expire in 7200 seconds [R0] Commit package(s) on R0
[R0] Finished Commit on R0
Checking status of Commit on [R0]
Commit: Passed on [R0]
Finished Commit

Install will reload the system now!
SUCCESS: install_add_activate_commit Thu Jul 22 01:31:23 UTC 2021
Jul 22 01:31:23.870 %INSTALL-5-INSTALL_COMPLETED_INFO: R0/0: install_engine: Completed install one-shot PACKAGE bootflash:csr1000v-universalk9.16.08.03.SPA.bin

csr1kv01#
Jul 22 01:31:23.854: %INSTALL-5-INSTALL_COMPLETED_INFO: R0/0: install_engine: Completed install one-shot PACKAGE bootflash:csr1000v-universalk9.16.08.03.SPA.bin

Log back into your IOS XE device and check the version

login as: jdoe
Keyboard-interactive authentication prompts from server:
| Password: **********

csr1kv01#show ver
Cisco IOS XE Software, Version 16.08.03
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.3, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2019 by Cisco Systems, Inc.
Compiled Tue 09-Apr-19 16:36 by mcpre



csr1kv01#show install summary
[ R0 ] Installed Package(s) Information:
State (St): I – Inactive, U – Activated & Uncommitted,


Auto abort timer: inactive

csr1kv01#dir | in .pkg
12 -rw- 381461464 May 25 2021 14:32:04 +00:00 csr1000v-mono-universalk9.16.08.02.SPA.pkg
13 -rw- 38555320 May 25 2021 14:32:04 +00:00 csr1000v-rpboot.16.08.02.SPA.pkg
162563 -rw- 381440984 Jul 22 2021 01:05:52 +00:00 csr1000v-mono-universalk9.16.08.03.SPA.pkg
162564 -rw- 38607815 Jul 22 2021 01:07:03 +00:00 csr1000v-rpboot.16.08.03.SPA.pkg

Check the flash and do a clean up using an Ansible script

[jdoe@centos8 testing_dir]$ cat delete1.yml

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
    - name: Tell user which is working node
      debug: msg="Working on {{ inventory_hostname }}"

    - name: Delete unused pkgs and images
      ios_command:
        commands:
          - command: "request platform software package clean"
            prompt: ']'
            answer: 'y'
      ignore_errors: yes

Directory before running above playbook

csr1kv01#dir
Directory of bootflash:/

11 drwx 16384 May 25 2021 14:31:12 +00:00 lost+found
365761 drwx 4096 Jul 22 2021 01:32:29 +00:00 .installer
12 -rw- 381461464 May 25 2021 14:32:04 +00:00 csr1000v-mono-universalk9.16.08.02.SPA.pkg
13 -rw- 38555320 May 25 2021 14:32:04 +00:00 csr1000v-rpboot.16.08.02.SPA.pkg
23 -rw- 1941 Jul 22 2021 01:30:41 +00:00 packages.conf
422657 drwx 4096 Jun 7 2021 00:30:48 +00:00 core
243841 drwx 4096 Jul 22 2021 12:34:17 +00:00 .prst_sync
113793 drwx 4096 Jul 22 2021 01:30:53 +00:00 .rollback_timer
260097 drwx 28672 Jul 22 2021 01:42:54 +00:00 tracelogs
146305 drwx 4096 May 25 2021 03:37:35 +00:00 .dbpersist
211329 drwx 4096 May 25 2021 14:33:44 +00:00 virtual-instance
15 -rw- 30 Jul 22 2021 12:34:14 +00:00 throughput_monitor_params
16 -rw- 0 Jul 22 2021 12:34:14 +00:00 cvac.log
333249 drwx 4096 May 25 2021 14:34:26 +00:00 onep
17 -rw- 157 Jul 22 2021 12:34:28 +00:00 csrlxc-cfg.log
18 -rw- 35 May 25 2021 03:36:18 +00:00 pnp-tech-time
19 -rw- 91053 May 25 2021 03:36:19 +00:00 pnp-tech-discovery-summary
20 -rw- 419950487 Jul 5 2021 06:45:10 +00:00 csr1000v-universalk9.16.08.03.SPA.bin
162563 -rw- 381440984 Jul 22 2021 01:05:52 +00:00 csr1000v-mono-universalk9.16.08.03.SPA.pkg
162564 -rw- 38607815 Jul 22 2021 01:07:03 +00:00 csr1000v-rpboot.16.08.03.SPA.pkg
162562 -rw- 2790 Jul 22 2021 01:07:05 +00:00 csr1000v-universalk9.16.08.03.SPA.conf
22 -rw- 1941 Jul 22 2021 01:30:41 +00:00 packages.conf.00-

7897796608 bytes total (6085701632 bytes free)

Run the playbook

[jdoe@centos8 testing_dir]$ ansible-playbook software_clean.yml

PLAY [csr1kv01] ******************************************************************************************************************************************************************************************************************

TASK [INFORM USER WHAT PLAYBOOK SCOPE IS] ****************************************************************************************************************************************************************************************
ok: [csr1kv01] => {
    "msg": "This playbook will be run against csr1kv01"
}

TASK [DELETE UNUSED IMAGES] ******************************************************************************************************************************************************************************************************
ok: [csr1kv01]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
csr1kv01                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Directory after running above playbook

csr1kv01#dir
Directory of bootflash:/

11 drwx 16384 May 25 2021 14:31:12 +00:00 lost+found
365761 drwx 4096 Jul 22 2021 01:32:29 +00:00 .installer
23 -rw- 1941 Jul 22 2021 01:30:41 +00:00 packages.conf
422657 drwx 4096 Jun 7 2021 00:30:48 +00:00 core
243841 drwx 4096 Jul 22 2021 12:34:17 +00:00 .prst_sync
113793 drwx 4096 Jul 22 2021 01:30:53 +00:00 .rollback_timer
260097 drwx 28672 Jul 22 2021 01:42:54 +00:00 tracelogs
146305 drwx 4096 May 25 2021 03:37:35 +00:00 .dbpersist
211329 drwx 4096 May 25 2021 14:33:44 +00:00 virtual-instance
15 -rw- 30 Jul 22 2021 12:34:14 +00:00 throughput_monitor_params
16 -rw- 0 Jul 22 2021 12:34:14 +00:00 cvac.log
333249 drwx 4096 May 25 2021 14:34:26 +00:00 onep
17 -rw- 157 Jul 22 2021 12:34:28 +00:00 csrlxc-cfg.log
18 -rw- 35 May 25 2021 03:36:18 +00:00 pnp-tech-time
19 -rw- 91053 May 25 2021 03:36:19 +00:00 pnp-tech-discovery-summary
162563 -rw- 381440984 Jul 22 2021 01:05:52 +00:00 csr1000v-mono-universalk9.16.08.03.SPA.pkg
162564 -rw- 38607815 Jul 22 2021 01:07:03 +00:00 csr1000v-rpboot.16.08.03.SPA.pkg

7897796608 bytes total (6926520320 bytes free)

Before yesterdayYour RSS feeds

Ansible – when, retries, until module

July 20th 2021 at 11:44

Modules:

when =

retries =

until =

delegate_to =

When, retries and until module can control the behaviour of the returned outcome based on the response.

---
- hosts: all
  gather_facts: no
  connection: local

  tasks:
    - name: purposely fail
      shell: ping -c 3 {{ inventory_hostname }}
      register: ping_response
      until: ping_response is not failed
      retries: 3
      ignore_errors: yes

    - name: debug ping response
      debug:
        msg: "{{ ping_response }}"
      when: ping_response is not failed

The effect

[jdoe@centos8 cisco_csr1k]$ ansible-playbook a1-1_3.yml

PLAY [all] *

TASK [purposely fail]
changed: [csr1kv02]
changed: [c8kv02]
changed: [c8kv01]
changed: [csr1kv01]
FAILED – RETRYING: purposely fail (1 retries left).
FAILED – RETRYING: purposely fail (1 retries left).
FAILED – RETRYING: purposely fail (1 retries left).
FAILED – RETRYING: purposely fail (1 retries left).
fatal: [wlc01]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 wlc01”, “delta”: “0:00:03.061694”, “end”: “2021-07-20 19:43:37.585494”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.523800”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING wlc01 (192.168.0.241) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— wlc01 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms\npipe 3”, “stdout_lines”: [“PING wlc01 (192.168.0.241) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— wlc01 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms”, “pipe 3”]}

ignoring
fatal: [csr1kv03]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 csr1kv03”, “delta”: “0:00:03.103826”, “end”: “2021-07-20 19:43:37.777578”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.673752”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING csr1kv03 (192.168.0.183) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— csr1kv03 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2063ms\npipe 3”, “stdout_lines”: [“PING csr1kv03 (192.168.0.183) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— csr1kv03 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2063ms”, “pipe 3”]}

ignoring
fatal: [c8kv03]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 c8kv03”, “delta”: “0:00:03.060089”, “end”: “2021-07-20 19:43:37.776701”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.716612”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING c8kv03 (192.168.0.193) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— c8kv03 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms\npipe 3”, “stdout_lines”: [“PING c8kv03 (192.168.0.193) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— c8kv03 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms”, “pipe 3”]}

ignoring
fatal: [wlc02]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 wlc02”, “delta”: “0:00:03.104390”, “end”: “2021-07-20 19:43:37.904509”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.800119”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING wlc02 (192.168.0.242) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— wlc02 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2071ms\npipe 3”, “stdout_lines”: [“PING wlc02 (192.168.0.242) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— wlc02 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2071ms”, “pipe 3”]}

ignoring

TASK [debug ping response] ***
ok: [csr1kv01] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 csr1kv01”,
“delta”: “0:00:02.072632”,
“end”: “2021-07-20 19:43:28.312930”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.240298”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING csr1kv01 (192.168.0.181) 56(84) bytes of data.\n64 bytes from csr1kv01 (192.168.0.181): icmp_seq=1 ttl=255 time=0.532 ms\n64 bytes from csr1kv01 (192.168.0.181): icmp_seq=2 ttl=255 time=0.599 ms\n64 bytes from csr1kv01 (192.168.0.181): icmp_seq=3 ttl=255 time=2.17 ms\n\n— csr1kv01 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2051ms\nrtt min/avg/max/mdev = 0.532/1.101/2.174/0.759 ms”,
“stdout_lines”: [
“PING csr1kv01 (192.168.0.181) 56(84) bytes of data.”,
“64 bytes from csr1kv01 (192.168.0.181): icmp_seq=1 ttl=255 time=0.532 ms”,
“64 bytes from csr1kv01 (192.168.0.181): icmp_seq=2 ttl=255 time=0.599 ms”,
“64 bytes from csr1kv01 (192.168.0.181): icmp_seq=3 ttl=255 time=2.17 ms”,
“”,
“— csr1kv01 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2051ms”,
“rtt min/avg/max/mdev = 0.532/1.101/2.174/0.759 ms”
]
}
}
skipping: [csr1kv03]
ok: [csr1kv02] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 csr1kv02”,
“delta”: “0:00:02.035590”,
“end”: “2021-07-20 19:43:28.238564”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.202974”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING csr1kv02 (192.168.0.182) 56(84) bytes of data.\n64 bytes from csr1kv02 (192.168.0.182): icmp_seq=1 ttl=255 time=0.607 ms\n64 bytes from csr1kv02 (192.168.0.182): icmp_seq=2 ttl=255 time=0.529 ms\n64 bytes from csr1kv02 (192.168.0.182): icmp_seq=3 ttl=255 time=0.540 ms\n\n— csr1kv02 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2006ms\nrtt min/avg/max/mdev = 0.529/0.558/0.607/0.043 ms”,
“stdout_lines”: [
“PING csr1kv02 (192.168.0.182) 56(84) bytes of data.”,
“64 bytes from csr1kv02 (192.168.0.182): icmp_seq=1 ttl=255 time=0.607 ms”,
“64 bytes from csr1kv02 (192.168.0.182): icmp_seq=2 ttl=255 time=0.529 ms”,
“64 bytes from csr1kv02 (192.168.0.182): icmp_seq=3 ttl=255 time=0.540 ms”,
“”,
“— csr1kv02 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2006ms”,
“rtt min/avg/max/mdev = 0.529/0.558/0.607/0.043 ms”
]
}
}
ok: [c8kv01] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 c8kv01”,
“delta”: “0:00:02.065711”,
“end”: “2021-07-20 19:43:28.302238”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.236527”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING c8kv01 (192.168.0.191) 56(84) bytes of data.\n64 bytes from c8kv01 (192.168.0.191): icmp_seq=1 ttl=255 time=0.235 ms\n64 bytes from c8kv01 (192.168.0.191): icmp_seq=2 ttl=255 time=0.197 ms\n64 bytes from c8kv01 (192.168.0.191): icmp_seq=3 ttl=255 time=0.291 ms\n\n— c8kv01 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2058ms\nrtt min/avg/max/mdev = 0.197/0.241/0.291/0.038 ms”,
“stdout_lines”: [
“PING c8kv01 (192.168.0.191) 56(84) bytes of data.”,
“64 bytes from c8kv01 (192.168.0.191): icmp_seq=1 ttl=255 time=0.235 ms”,
“64 bytes from c8kv01 (192.168.0.191): icmp_seq=2 ttl=255 time=0.197 ms”,
“64 bytes from c8kv01 (192.168.0.191): icmp_seq=3 ttl=255 time=0.291 ms”,
“”,
“— c8kv01 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2058ms”,
“rtt min/avg/max/mdev = 0.197/0.241/0.291/0.038 ms”
]
}
}
skipping: [c8kv03]
ok: [c8kv02] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 c8kv02”,
“delta”: “0:00:02.103911”,
“end”: “2021-07-20 19:43:28.302508”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.198597”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING c8kv02 (192.168.0.192) 56(84) bytes of data.\n64 bytes from c8kv02 (192.168.0.192): icmp_seq=1 ttl=255 time=0.289 ms\n64 bytes from c8kv02 (192.168.0.192): icmp_seq=2 ttl=255 time=0.206 ms\n64 bytes from c8kv02 (192.168.0.192): icmp_seq=3 ttl=255 time=0.220 ms\n\n— c8kv02 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2065ms\nrtt min/avg/max/mdev = 0.206/0.238/0.289/0.038 ms”,
“stdout_lines”: [
“PING c8kv02 (192.168.0.192) 56(84) bytes of data.”,
“64 bytes from c8kv02 (192.168.0.192): icmp_seq=1 ttl=255 time=0.289 ms”,
“64 bytes from c8kv02 (192.168.0.192): icmp_seq=2 ttl=255 time=0.206 ms”,
“64 bytes from c8kv02 (192.168.0.192): icmp_seq=3 ttl=255 time=0.220 ms”,
“”,
“— c8kv02 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2065ms”,
“rtt min/avg/max/mdev = 0.206/0.238/0.289/0.038 ms”
]
}
}
skipping: [wlc01]
skipping: [wlc02]

PLAY RECAP *
c8kv01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c8kv02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c8kv03 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
csr1kv01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
csr1kv02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
csr1kv03 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
wlc01 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
wlc02 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1

italchemy

Ansible – Error handling by using block and rescue

July 20th 2021 at 09:42

While developing ansible automation code, I wanted to test the port 22 reachability. If any host is not reachable, then it will throw a Failed error and it gets classified as failed. When you use rescue, this error can be handled more gracefully. Here is how it is done.

I have 4 active hosts and 1 inactive host. When 1 inactive host throws an error, it should be handled by rescue module.

Ansible.cfg file

[defaults]
inventory=inventory
host_key_checking=False
#timeout = 30
nocows = 1
deprecation_warnings = False
retry_files_enabled = False
log_path = ./csr1k_ansible.log
forks = 30
interpreter_python=auto_silent
#ansible_python_interpreter: /usr/bin/python3
[persistent_connection]
command_timeout = 240

Inventory file

[ios:vars]
ansible_network_os=ios
ansible_user=cisco
ansible_password=K0ala123

[ios:children]
routers
switches

[routers]
csr1kv01 ansible_host=192.168.0.181
csr1kv02 ansible_host=192.168.0.182
csr1kv03 ansible_host=192.168.0.183   <<< This one is inactive

[switches]
c8kv01 ansible_host=192.168.0.191
c8kv02 ansible_host=192.168.0.192

The Original playbook

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
    - block:
        - wait_for_connection:
            sleep: 1
            timeout: 5


    - debug:
        msg: "{{ inventory_hostname }} is running"

Run the playbook

[jdoe@centos8 cisco_csr1k]$ ansible-playbook a1-1_2.yml

PLAY [all] ***********************************************************************************************************************************************************************************************************************

TASK [wait_for_connection] *******************************************************************************************************************************************************************************************************
ok: [c8kv01]
ok: [csr1kv01]
ok: [c8kv02]
ok: [csr1kv02]
fatal: [csr1kv03]: FAILED! => {"changed": false, "elapsed": 25, "msg": "timed out waiting for connection port up: [Errno None] Unable to connect to port 22 on 192.168.0.183"}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [c8kv01] => {
    "msg": "c8kv01 is running"
}
ok: [c8kv02] => {
    "msg": "c8kv02 is running"
}
ok: [csr1kv01] => {
    "msg": "csr1kv01 is running"
}
ok: [csr1kv02] => {
    "msg": "csr1kv02 is running"
}

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c8kv02                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv01                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv02                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv03                   : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Now, I want to change failed=1 to rescued=1.

Updated Playbook

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
    - block:
        - wait_for_connection:
            sleep: 1
            timeout: 5
      rescue:
        - debug:
            msg: "{{ inventory_hostname }} not connected. End of host."
        - meta: clear_host_errors
        - meta: end_host

    - debug:
        msg: "{{ inventory_hostname }} is running"

Run the playbook again

[jdoe@centos8 cisco_csr1k]$ ansible-playbook a1-1_2.yml

PLAY [all] ***********************************************************************************************************************************************************************************************************************

TASK [wait_for_connection] *******************************************************************************************************************************************************************************************************
ok: [csr1kv02]
ok: [c8kv01]
ok: [c8kv02]
ok: [csr1kv01]
fatal: [csr1kv03]: FAILED! => {"changed": false, "elapsed": 25, "msg": "timed out waiting for connection port up: [Errno None] Unable to connect to port 22 on 192.168.0.183"}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv03] => {
    "msg": "csr1kv03 not connected. End of host."
}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv01] => {
    "msg": "csr1kv01 is running"
}
ok: [c8kv01] => {
    "msg": "c8kv01 is running"
}
ok: [csr1kv02] => {
    "msg": "csr1kv02 is running"
}
ok: [c8kv02] => {
    "msg": "c8kv02 is running"
}

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c8kv02                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv01                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv02                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv03                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

Now the failed error message has been handled correctly and evrything is green.

Bonus: this is another communication test YAML script without the rescue option. Change the port number as required.

---
- hosts: all
  gather_facts: no
  connection: network_cli

  tasks:
    - name: Filter unreachable devices
      wait_for: host="{{ inventory_hostname }}" port=22 timeout=3
    - debug: msg="port 22 OK"

    - name: CHECK CURRENT VERSION
      ios_facts:

    - debug:
        msg:
        - 'Current version is {{ ansible_net_version }}'
PLAY [all] ***********************************************************************************************************************************************************************************************************************

TASK [Filter unreachable devices] ************************************************************************************************************************************************************************************************
ok: [csr1kv02]
ok: [c8kv01]
ok: [csr1kv01]
ok: [c8kv02]
fatal: [csr1kv03]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": false, "elapsed": 2, "msg": "Timeout when waiting for csr1kv03:22"}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv02] => {
    "msg": "port 22 OK"
}
ok: [c8kv01] => {
    "msg": "port 22 OK"
}
ok: [csr1kv01] => {
    "msg": "port 22 OK"
}
ok: [c8kv02] => {
    "msg": "port 22 OK"
}

TASK [CHECK CURRENT VERSION] *****************************************************************************************************************************************************************************************************
[WARNING]: default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards
ok: [c8kv01]
ok: [c8kv02]
ok: [csr1kv01]
ok: [csr1kv02]

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv01] => {
    "msg": [
        "Current version is 16.08.02"
    ]
}
ok: [csr1kv02] => {
    "msg": [
        "Current version is 16.08.02"
    ]
}
ok: [c8kv02] => {
    "msg": [
        "Current version is 17.04.01b"
    ]
}
ok: [c8kv01] => {
    "msg": [
        "Current version is 17.04.01b"
    ]
}

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c8kv02                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv01                   : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv02                   : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv03                   : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

italchemy

Cent OS 8 – Add SFTP service [2/2], install nmap on Ubuntu 20 to scan port and test SFTP

July 20th 2021 at 02:48

This is the continuation of the previous post. Here, we will install the nmap package to another Linux server (192.168.0.251) and test the open ports on the SFTP server, a router and a switch.

Check nmap package

jdoe@u20s:~$ sudo apt list nmap
[sudo] password for jdoe: **********
Listing
 Done
nmap/focal 7.80+dfsg1-2build1 amd64

# Install nmap

jdoe@u20s:~$ sudo apt install nmap -y
Reading package lists
 Done
Building dependency tree
Reading state information
 Done
The following packages were automatically installed and are no longer required:
ieee-data python3-argcomplete python3-dnspython python3-jmespath
python3-kerberos python3-libcloud python3-lockfile python3-netaddr
python3-ntlm-auth python3-requests-kerberos python3-requests-ntlm
python3-selinux python3-winrm python3-xmltodict squashfs-tools tcpd

 [ommitted for brevity]
Processing triggers for man-db (2.9.1-1) 

Processing triggers for libc-bin (2.31-0ubuntu9.2) 


jdoe@u20s:~$ nmap –version
Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1d nmap-libssh2-1.8.2 libz-1.2.11 libpcre-8.39 libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

Run nmap against another Linux server

jdoe@u20s:~$ sudo nmap -n 192.168.0.252 <<< Red Hat (CentOS) Linux IP
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-20 00:22 UTC
Nmap scan report for 192.168.0.252
Host is up (0.00013s latency).
Not shown: 968 filtered ports, 28 closed ports
PORT STATE SERVICE
21/tcp open ftp <<< This port is used for FTP for vsftpd
22/tcp open ssh <<< Port is available for SFTP for Open SSH
80/tcp open http
443/tcp open https
MAC Address: 00:0C:29:BE:CA:A5 (VMware)

Run nmap against a Cisco router

jdoe@u20s:~$ sudo nmap -n 192.168.0.181 <<< Cisco router IP
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-20 00:26 UTC
Nmap scan report for 192.168.0.181
Host is up (0.00096s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
8090/tcp open opsmessaging
MAC Address: 00:0C:29:07:29:B5 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.67 seconds

Run nmap against a Cisco switch

jdoe@u20s:~$ sudo nmap -n 192.168.0.245 <<< Cisco switch IP
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-20 00:29 UTC
Nmap scan report for 192.168.0.245
Host is up (0.00082s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
MAC Address: 00:0C:29:0C:78:BF (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.72 seconds

Access SFTP server from another Linux server

jdoe@u20s:~$ sftp sftpuser@192.168.0.252
The authenticity of host ‘192.168.0.252 (192.168.0.252)’ can’t be established.
ECDSA key fingerprint is SHA256:UMZoyCaK2sMR2zEI9JAVRxFtSxbPhRwp1nnL77qKyfo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added ‘192.168.0.252’ (ECDSA) to the list of known hosts.

sftpuser@192.168.0.252’s password: **********
Connected to 192.168.0.252.
sftp> pwd
Remote working directory: /upload
sftp> dir -lh
-rw-r–r– ? 1003 1003 3.6M Jul 22 2020 4MB.bin
-rw-r–r– ? 0 0 10B Jul 19 07:02 sftptest999.txt

Get (download) a test file to your remote machine.

sftp> get sftptest999.txt
Fetching /upload/sftptest999.txt to sftptest999.txt
/upload/sftptest999.txt 100% 10 0.9KB/s 00:00
sftp> ^Z
[1]+ Stopped sftp sftpuser@192.168.0.252

jdoe@u20s:~$ ls -lh | grep sftp*
-rw-r–r– 1 jdoe jdoe 10 Jul 20 00:38 sftptest999.txt

You cannot ssh into this server.

jdoe@u20s:~$ ssh sftpuser@192.168.0.252
sftpuser@192.168.0.252’s password:
This service allows sftp connections only.
Connection to 192.168.0.252 closed.

Source: https://www.howtoforge.com/tutorial/how-to-setup-an-sftp-server-on-centos/

italchemy

Cent OS 8 – Add SFTP service [1/2]

July 19th 2021 at 09:25

Note: Assumption, it is assumed that you already have vsftpd and open ssh server installed.

SFTP need to be configured using SSH server.

Add a new group for sftpusers, here I am using the group name as sftpusers

[jdoe@centos8 cisco_csr1k]$ sudo groupadd sftpusers

Try to crete a new user and add to this group, since I have an existing user, I will delete the user and recreat it.

[jdoe@centos8 cisco_csr1k]$ sudo useradd -g sftpusers -d /upload -s /sbin/nologin sftpuser
useradd: user ‘sftpuser’ already exists

Since the user is hogging a process, I need to kill it using the kill -9 command

[jdoe@centos8 cisco_csr1k]$ sudo userdel -r sftpuser
userdel: user sftpuser is currently used by process 21383
[jdoe@centos8 cisco_csr1k]$ sudo kill -9 21383
[jdoe@centos8 cisco_csr1k]$ sudo userdel -r sftpuser

Recreate the user for sftp upload/download

[jdoe@centos8 cisco_csr1k]$ sudo useradd -g sftpusers -d /upload -s /sbin/nologin sftpuser
[jdoe@centos8 cisco_csr1k]$ sudo passwd sftpuser
Changing password for user sftpuser.
New password: Retype new password:
passwd: all authentication tokens updated successfully.

Make SFTP directory. Here create a root directory called upload and this is where all the files will be placed.

[jdoe@centos8 /]$ pwd
/
[jdoe@centos8 /]$ sudo mkdir -p /data/sftp
[jdoe@centos8 /]$ sudo chmod 705 /data

[jdoe@centos8 /]$ sudo mkdir -p /data/sftpuser/upload
[jdoe@centos8 /]$ sudo chown -R root:sftpusers /data/sftpuser
[jdoe@centos8 /]$ sudo chown -R sftpuser:sftpusers /data/sftpuser/upload

[jdoe@centos8 /]$ ls -ld /data
drwx—r-x. 4 root root 34 Jul 19 16:54 /data
[jdoe@centos8 /]$ ls -ld /data/sftpuser
drwxr-xr-x. 3 root sftpusers 20 Jul 19 16:54 /data/sftpuser
[jdoe@centos8 /]$ ls -ld /data/sftpuser/upload
drwxr-xr-x. 2 sftpuser sftpusers 6 Jul 19 16:54 /data/sftpuser/upload
[jdoe@centos8 /]$ sudo nano /etc/ssh/sshd_config

Go to /etc/ssh/sshd_config and add the following lines at the end.

[jdoe@centos8 /]$ nano /etc/ssh/sshd_config



Match Group sftpusers
ChrootDirectory /data/%u
ForceCommand internal-sftp

Restart SSHD service

[jdoe@centos8 /]$ service sshd restart
Redirecting to /bin/systemctl restart sshd.service
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to restart ‘sshd.service’.
Authenticating as: John Doe (jdoe)
Password:
==== AUTHENTICATION COMPLETE ====

Check SSHD service

[jdoe@centos8 /]$ service sshd status
Redirecting to /bin/systemctl status sshd.service
● sshd.service – OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-07-19 16:58:27 AEST; 2s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 23475 (sshd)
Tasks: 1 (limit: 23532)
Memory: 1.1M
CGroup: /system.slice/sshd.service
└─23475 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc -oMACs=hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh>

Jul 19 16:58:27 centos8 systemd[1]: Stopped OpenSSH server daemon.
Jul 19 16:58:27 centos8 systemd[1]: Starting OpenSSH server daemon

Jul 19 16:58:27 centos8 sshd[23475]: Server listening on 0.0.0.0 port 22.
Jul 19 16:58:27 centos8 sshd[23475]: Server listening on :: port 22.
Jul 19 16:58:27 centos8 systemd[1]: Started OpenSSH server daemon.

Create or add test files

[jdoe@centos8 /]$ sudo touch /data/sftpuser/upload/sftptest999.txt
[jdoe@centos8 /]$ ls /data/sftpuser/upload/ -lh
total 3.6M
-rw-r–r–. 1 sftpuser sftpusers 3.6M Jul 22 2020 4MB.bin
-rw-r–r–. 1 root root 10 Jul 19 17:02 sftptest999.txt

============================

Verification

c9800-cl#copy sftp://sftpuser:K0ala123@192.168.0.252/sftptest999.txt flash:/sftptest999.txt
Destination filename [sftptest999.txt]?
0 bytes copied in 0.285 secs (0 bytes/sec)

c9800-cl#$K0ala123@192.168.0.252/4MB.bin flash:/sftptest_4MB.bin
Destination filename [sftptest_4MB.bin]?
!!!!!!!!!!!!!!!!!!!!
3752704 bytes copied in 3.467 secs (1082407 bytes/sec)

c9800-cl#
c9800-cl#dir | in sftptest
23 -rw- 10 Jul 19 2021 18:03:29 +00:00 sftptest999.txt
24 -rw- 3752704 Jul 19 2021 18:07:24 +00:00 sftptest_4MB.bin

This is the debug of file transfer on Cisco device.

Jul 19 18:03:29.243:  SFTP rcv_stub: buffsize (140694477057376) verbose (0) filename (sftptest999.txt)
Jul 19 18:03:29.243: SFTP rcv: Starting download procedure for sftptest999.txt with buf_size (8192)
Jul 19 18:03:29.243: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_INIT bytes req (9) written (9)
Jul 19 18:03:29.246: SFTP get_string: msg_size = 179 length = 4096
Jul 19 18:03:29.246: SFTP: [54291 <- 192.168.0.252:22] recv SFTP do_init: Remote server version: 3
Jul 19 18:03:29.246: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_REALPATH for .
Jul 19 18:03:29.249: SFTP get_string: msg_size = 35 length = 4096
Jul 19 18:03:29.249: SFTP: [54291 <- 192.168.0.252:22] recv SFTP do_realpath: record count (1)
Jul 19 18:03:29.249: SFTP: [54291 -> 192.168.0.252:22] send SFTP rcv: Looking up /upload/sftptest999.txt
Jul 19 18:03:29.249: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_STAT for /upload/sftptest999.txt
Jul 19 18:03:29.250: SFTP get_string: msg_size = 37 length = 4096
Jul 19 18:03:29.250: SFTP: [54291 <- 192.168.0.252:22] recv SSH2_FXP_STAT attribs
Jul 19 18:03:29.250: SFTP rcv: file size (10) avail space (-1)
Jul 19 18:03:29.250: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_OPEN for /upload/sftptest999.txt (44)
Jul 19 18:03:29.251: SFTP get_string: msg_size = 13 length = 4096
Jul 19 18:03:29.251: SFTP rcv: Start fetching /upload/sftptest999.txt .

Jul 19 18:03:29.251: SFTP: [54291 -> 192.168.0.252:22] send SFTP rcv: Request server to send (8162) bytes data
Jul 19 18:03:29.251: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_READ bytes req (29) written (29)
Jul 19 18:03:29.252: SFTP get_string: msg_size = 19 length = 8192
Jul 19 18:03:29.252: SFTP fioctl: rcvd req 5
Jul 19 18:03:29.253: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_READ bytes req (29) written (29)
Jul 19 18:03:29.253: SFTP get_string: msg_size = 28 length = 8192
Jul 19 18:03:29.253: SFTP: [54291 <- 192.168.0.252:22] recv SFTP rcv: SSH2_FX_EOF
Jul 19 18:03:29.254: SFTP: [54291 <- 192.168.0.252:22] recv SFTP rcv: 10 bytes
Jul 19 18:03:29.254: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_CLOSE
Jul 19 18:03:29.255: SFTP get_string: msg_size = 24 length = 4096
Jul 19 18:03:29.256: SFTP fioctl: rcvd req 3
Jul 19 18:03:29.256: SFTP ifs_close: Read Operation

Source: https://www.howtoforge.com/tutorial/how-to-setup-an-sftp-server-on-centos/

italchemy

Les problÚmes gris dans les réseaux informatiques

Une passionnante discussion sur la liste NANOG vient de porter sur les « problÚmes gris ». Qu'est-ce qu'un problÚme gris en matiÚre de réseaux informatiques ?

Les rĂ©seaux ne sont pas fiables, toute personne qui a dĂ©jĂ  vu un message « Connection time out » peut en tĂ©moigner. De l'erreur de configuration chez un opĂ©rateur Ă  l'attaque d'une pelleteuse sur une fibre, en passant par une bogue dans les routeurs, les causes de panne ne manquent pas. Ces pannes sont typiquement binaires : soit toutes les communications passent, soit aucune ne passe. À dĂ©faut d'ĂȘtre faciles Ă  prĂ©venir, ou mĂȘme Ă  rĂ©parer, ces pannes sont triviales Ă  dĂ©tecter : la supervision couine et les utilisateurs rĂąlent. Mais il y a aussi des pannes « grises ». C'est quand ça dĂ©conne mais pas de maniĂšre binaire : la grande majoritĂ© du trafic passe (et on peut donc ne s'apercevoir de rien) mais le problĂšme gris frappe une petite minoritĂ© des paquets, selon des critĂšres qui ne sont pas Ă©vidents Ă  premiĂšre vue. Par exemple, le rĂ©seau laisse passer tous les paquets, sauf ceux qui ont telle combinaison d'options. Ou bien il laisse passer 99,99 % des paquets mais jette les autres (en dehors du cas de congestion, oĂč il est normal de jeter les paquets). Dans la discussion sur NANOG, un ingĂ©nieur citait un cas qu'il avait rencontrĂ© oĂč une line card dĂ©faillante jetait tous les paquets IPv6 oĂč le 65e bit de l'adresse de destination Ă©tait Ă  1 (ce qui est apparemment assez rare). Le terme a Ă©tĂ© utilisĂ© dans d'autres contextes que le rĂ©seau (par exemple cette Ă©tude de Microsoft).

La discussion sur la liste NANOG avait Ă©tĂ© lancĂ©e dans le contexte d'une Ă©tude de l'École polytechnique de Zurich, Ă©tude qui commençait par un sondage auprĂšs des opĂ©rateurs pour leur demander s'ils gĂ©raient les problĂšmes gris et comment.

D'abord, une constatation peu originale mais qu'il est important de rappeler. MĂȘme en dehors de la congestion, aucun rĂ©seau ne transporte 100 % des paquets. Il y a toujours des problĂšmes, les rĂ©seaux Ă©tant des objets physiques, soumis aux lois de la physique et aux perturbations diverses (comme les rayons cosmiques). Aucune machine n'est idĂ©ale, l'Ă©lectronique n'est pas virtuelle et est donc imparfaite, la mĂ©moire d'un routeur ne garde pas forcĂ©ment intact ce qu'on lui a confiĂ©. Et, non, FCS et ECC ne dĂ©tectent pas tous les problĂšmes. Comme le notait un observateur : « De ma longue expĂ©rience, j'en ai tirĂ© une analyse (trĂšs pertinente) : en informatique il y a entre 1 % et 2 % de magie. C'est faux, mais ça soulage parfois de se dire qu'on est peut ĂȘtre la cible d'un sortilĂšge vaudou ou sous la coupe d'une bonne fĂ©e. » Si un opĂ©rateur prĂ©tendait sincĂšrement ne pas avoir de problĂšmes gris, cela indiquerait une absence de recherche plutĂŽt qu'une absence de problĂšme. Fermer les yeux permet de dormir mieux :-)

Les problÚmes gris sont trÚs difficiles à détecter. Supposons que, comme tout bon ingénieur, vous avez un systÚme de supervision automatique qui fonctionne, mettons, en envoyant des messages ICMP de type Echo et en attendant une réponse. Si vous envoyez trois paquets par test, et que le réseau jette 1 % des paquets (un chiffre trÚs élevé) au hasard, vous n'avez qu'une chance sur un demi-million de détecter le problÚme. Bien sûr, on ne se contente pas de ce genre de tests. On regarde par exemple les compteurs attachés aux interfaces des routeurs et on regarde si les compteurs d'erreur grimpent. Mais si c'est l'électronique des routeurs qui est défaillante, les compteurs ne seront pas fiables.

Les problĂšmes gris sont parfois dĂ©terministes (comme dans l'exemple du bit 65 plus haut) mais pas toujours et, s'ils ne sont pas reproductibles, le problĂšme est encore pire. MĂȘme s'ils sont dĂ©terministes, l'algorithme n'est pas forcĂ©ment Ă©vident. Si les paquets sont aiguillĂ©s Ă  l'intĂ©rieur d'un Ă©quipement selon des critĂšres complexes, et qu'un seul des circuits est dĂ©faillant, vous ne trouverez pas forcĂ©ment tout de suite pourquoi, des fois, ça passe et, des fois, ça ne passe pas.

Est-ce grave pour l'opĂ©rateur ? Dans la discussion sur NANOG, un participant a dit franchement que les problĂšmes gris Ă©taient frĂ©quents mais tellement difficiles Ă  traiter (par exemple parce qu'ils impliquent souvent de longues et difficiles nĂ©gociations avec les vendeurs de matĂ©riel) qu'il valait mieux les ignorer, sauf si un client rĂąlait. Mais, justement, le client ne rĂąle pas toujours si le problĂšme est rare, et difficile Ă  pointer du doigt avec prĂ©cision. Et puis les systĂšmes modernes comportent tellement de couches superposĂ©es que le client a le plus grand mal Ă  trouver l'origine d'un problĂšme. Ainsi, dans le cas d'un problĂšme spĂ©cifique Ă  IPv6, comme celui citĂ© plus haut, le fait que le navigateur Web typique se rabatte automatiquement et rapidement en IPv4 n'aide pas au diagnostic (mĂȘme si c'est certainement mieux pour le bonheur de l'utilisateur).

Pour donner une idée de la subtilité des problÚmes gris, un participant à NANOG citait un cas d'un commutateur qui perdait 0,00012 % des paquets, un nombre difficile à repérer au milieu des erreurs de mesure. Le problÚme avait été détecté lors du remplacement des anciens tests (genre les trois messages ICMP cités plus haut) par des tests plus violents.

Bref, quand vous (enfin, votre navigateur Web) avez rĂ©cupĂ©rĂ© cet article, peut-ĂȘtre un problĂšme gris a-t-il perturbĂ© cette rĂ©cupĂ©ration. Peut-ĂȘtre n'a-t-il mĂȘme pas Ă©tĂ© dĂ©tectĂ© et le texte que vous lisez n'est pas le bon


RFC 8984: JSCalendar: A JSON Representation of Calendar Data

Beaucoup d'applications gÚrent des agendas, avec des réunions à ne pas oublier, des évÚnements récurrents, des rendez-vous précis. Le format traditionnel d'échange de ces applications est iCalendar, normalisé dans le RFC 5545 (ou, dans sa déclinaison en JSON, jCal, dans le RFC 7265). Ce RFC propose une syntaxe JSON mais, surtout, un modÚle de données trÚs différent, JSCalendar. Le but est de remplacer iCalendar.

Les principes de base ? SimplicitĂ© (au moins dans les cas simples, car les calendriers sont des bĂȘtes compliquĂ©es
), uniformitĂ© (autant que possible, une seule façon de reprĂ©senter un Ă©vĂšnement), tout en essayant de permettre des conversions depuis iCalendar (RFC 5545 et RFC 7986), donc en ayant un modĂšle de donnĂ©es compatible. JSCalendar, comme son nom l'indique, utilise JSON, plus exactement le sous-ensemble i-JSON, normalisĂ© dans le RFC 7493.

Bon, mais pourquoi ne pas avoir gardĂ© iCalendar ? Parce qu'il est trop complexe avec plusieurs formats de date, parce que ses rĂšgles de rĂ©currence sont ambigĂŒes et difficiles Ă  comprendre, parce que sa syntaxe est mal dĂ©finie. jCal n'a pas ce dernier problĂšme mais il garde tous les autres. On voit mĂȘme des logiciels utiliser leur propre reprĂ©sentation en JSON des donnĂ©es iCalendar au lieu d'utiliser jCal. Bref, JSCalendar prĂ©fĂšre repartir, sinon de zĂ©ro, du moins d'assez loin.

Voici un exemple trÚs simple et trÚs minimal de représentation d'un évÚnement en JSCalendar :

{
     "@type": "Event",
     "uid": "a8df6573-0474-496d-8496-033ad45d7fea",
     "updated": "2020-01-02T18:23:04Z",
     "title": "Some event",
     "start": "2020-01-15T13:00:00",
     "timeZone": "America/New_York",
     "duration": "PT1H"
}
  
Comme avec iCalendar, les donnĂ©es JSCalendar peuvent ĂȘtre Ă©changĂ©es par courrier ou avec n'importe quel autre protocole de son choix comme JMAP ou WebDAV.

Avant d'attaquer ce format JSCalendar, rappelez-vous qu'il utilise JSON et que la terminologie est celle de JSON. Ainsi, on nomme « objet » ce qui, selon le langage utilisé, serait un dictionnaire ou un tableau associatif. Ensuite, outre les types de base de JSON, JSCalendar a des types supplémentaires (section 1), notamment :

  • Id, un identificateur, pour que les objets aient un nom simple et unique (c'est une chaĂźne de caractĂšres JSON). On peut par exemple utiliser un UUID (RFC 4122). Dans l'exemple ci-dessus, le membre uid de l'objet est un Id.
  • UTCDateTime, une date-et-heure (un instant dans le temps) au format du RFC 3339 dans une chaĂźne de caractĂšres JSON, est obligatoirement en UTC. Un tel type est intĂ©ressant pour les Ă©vĂšnements internationaux comme une vidĂ©oconfĂ©rence. Dans l'exemple ci-dessus, le membre updated est de ce type.
  • LocalDateTime, une date-et-heure selon le fuseau horaire local. Un tel type est utile pour les Ă©vĂšnements locaux, comme un pique-nique. Dans l'exemple ci-dessus, qui concerne une rĂ©union en prĂ©sentiel, start est de ce type. On a besoin des deux types, Ă  la fois parce que les Ă©vĂšnements en distanciel et en prĂ©sentiel n'ont pas les mĂȘmes besoins, et aussi parce que le dĂ©calage entre les deux peut varier. Les calendriers, c'est compliquĂ© et le RFC cite l'exemple de la LocalDateTime 2020-10-04T02:30:00 qui n'existe pas Ă  Melbourne car le passage Ă  l'heure d'Ă©tĂ© fait qu'on saute de 2h Ă  3h, mais qui peut apparaitre dans les calculs (start + une durĂ©e) ou bien si les rĂšgles de l'heure d'Ă©tĂ© changent.
  • Duration est une durĂ©e, exprimĂ©e comme en iCalendar (PT1H pour « une heure » dans l'exemple ci-dessus, ce serait P1Y pour une annĂ©e). Gag : une journĂ©e (P1D) ne fait pas forcĂ©ment 24 heures, par exemple si on passe Ă  l'heure d'Ă©tĂ© pendant cette journĂ©e.
  • SignedDuration, une durĂ©e qui peut ĂȘtre nĂ©gative.
  • TimeZoneId, un identifiant pour un fuseau horaire, pris dans la base de l'IANA, par exemple Europe/Paris.
  • PatchObject est un pointeur JSON (ces pointeurs sont normalisĂ©s dans le RFC 6901) qui permet de dĂ©signer un objet Ă  modifier.
  • Relation est un objet, et plus un simple type scalaire comme les prĂ©cĂ©dents. Il permet d'indiquer une relation entre deux objets, notamment vers un objet parent ou enfant..
  • Link est Ă©galement une relation et donc un objet, mais vers le monde extĂ©rieur. Il a des propriĂ©tĂ©s comme href (dont la valeur est, comme vous vous en doutez, un URI) ou cid qui identifie le contenu vers lequel on pointe, dans la syntaxe du RFC 2392.
Les types de JSCalendar figurent dans un registre IANA, qu'on peut remplir avec la procédure « Examen par un expert » du RFC 8126.

Bien, maintenant que nous avons tous nos types, construisons des objets. Il y en a de trois types (section 2) :

  • Event (l'exemple ci-dessus, regardez sa propriĂ©tĂ© @type) est un Ă©vĂšnement ponctuel, par exemple une rĂ©union professionnelle ou une manifestation de rue. Il a une date-et-heure de dĂ©part, et une durĂ©e.
  • Task est une tĂąche Ă  accomplir, elle peut avoir une date-et-heure limite et peut avoir une durĂ©e estimĂ©e.
  • Group est un groupe d'Ă©vĂšnements JSCalendar.

JSCalendar n'a pas de rÚgles de canonicalisation (normalisation) générales, car cela dépend trop de considérations sémantiques que le format ne peut pas connaitre. Par exemple, JSON permet des tableaux, et JSCalendar utilise cette possibilité mais, quand on veut décider si deux tableaux sont équivalents, doit-on tenir compte de l'ordre des éléments ([1, 2] == [2, 1]) ? Cela dépend de l'application et JSCalendar ne fixe donc pas de rÚgles pour ce cas. (Un cas rigolo et encore pire est celui des valeurs qui sont des URI puisque la canonicalisation des URI dépend du plan - scheme.)

Quelles sont les propriétés typiques des objets JSCalendar (section 4) ? On trouve notamment, communs aux trois types d'objets (évÚnement, tùche et groupe) :

  • @type, le type d'objet (Event dans l'exemple ci-dessus, un des trois types possibles).
  • uid (a8df6573-0474-496d-8496-033ad45d7fea dans l'exemple), l'identificateur de l'objet (il est recommandĂ© que ce soit un des UUID du RFC 4122).
  • prodID, un identificateur du logiciel utilisĂ©, un peu comme le User-Agent: de HTTP. Le RFC suggĂšre d'utiliser un FPI.
  • updated, une date-et-heure de type UTCDateTime.
  • title et description, des chaĂźnes de caractĂšres utiles.
  • locations (notez le S) qui dĂ©signe les lieux physiques de l'Ă©vĂšnement. C'est compliquĂ©. Chaque lieu est un objet de type Location qui a comme propriĂ©tĂ©s possibles un type (tirĂ© du registre des types de lieux crĂ©Ă© par le RFC 4589), et une localisation sous forme de latitude et longitude (RFC 5870).
  • Tous les Ă©vĂšnements ne sont pas dans le monde physique, certains se produisent en ligne, d'oĂč le virtualLocations, qui indique des informations comme l'URI (via la propriĂ©tĂ© du mĂȘme nom). Ainsi, une confĂ©rence en ligne organisĂ©e par l'assocation Parinux via BigBlueButton aura comme virtualLocations {"@type": "VirtualLocation", "uri": "https://bbb.parinux.org/b/ca--xgc-4r3-n8z", 
}.
  • color permet de suggĂ©rer au logiciel une couleur Ă  utiliser pour l'affichage, qui est une valeur RGB en hexadĂ©cimal ou bien un nom de couleur CSS.
Et je suis loin d'avoir cité toutes les propriétés possibles, sans compter celles spécifiques à un type d'objet.

Pour le cas de locations, le RFC fournit un exemple de vol international (quand il était encore possible de prendre l'avion) :

   {
     "...": "",
     "title": "Flight XY51 to Tokyo",
     "start": "2020-04-01T09:00:00",
     "timeZone": "Europe/Berlin",
     "duration": "PT10H30M",
     "locations": {
       "418d0b9b-b656-4b3c-909f-5b149ca779c9": {
         "@type": "Location",
         "rel": "start",
         "name": "Frankfurt Airport (FRA)"
       },
       "c2c7ac67-dc13-411e-a7d4-0780fb61fb08": {
         "@type": "Location",
         "rel": "end",
         "name": "Narita International Airport (NRT)",
         "timeZone": "Asia/Tokyo"
       }
     }
   }
  
Notez les UUID pour identifier les lieux, et le changement de fuseau horaire entre le départ et l'arrivée. Si l'évÚnement a lieu à la fois en présentiel et en distanciel (ici, le concert est dans un lieu physique identifié par ses coordonnées géographiques, mais aussi diffusé en ligne), cela peut donner :
{
  "...": "",
  "title": "Live from Music Bowl: The Band",
  "description": "Go see the biggest music event ever!",
  "locale": "en",
  "start": "2020-07-04T17:00:00",
  "timeZone": "America/New_York",
  "duration": "PT3H",
  "locations": {
    "c0503d30-8c50-4372-87b5-7657e8e0fedd": {
      "@type": "Location",
      "name": "The Music Bowl",
      "description": "Music Bowl, Central Park, New York",
      "coordinates": "geo:40.7829,-73.9654"
    }
  },
  "virtualLocations": {
    "1": {
      "@type": "VirtualLocation",
      "name": "Free live Stream from Music Bowl",
      "uri": "https://stream.example.com/the_band_2020"
    }
    },
    ...
  

Les fournisseurs de logiciel peuvent ajouter des propriĂ©tĂ©s dĂ©finies par eux. Dans ce cas, le RFC recommande fortement qu'ils les nomment en les faisant prĂ©cĂ©der d'un nom de domaine identifiant le fournisseur. Si celui-ci a example.com et veut une propriĂ©tĂ© toto, il la nommera example.com:toto. C'est Ă©videmment une solution temporaire, les fournisseurs ont tout intĂ©rĂȘt Ă  enregistrer ces propriĂ©tĂ©s pour qu'elles puissent servir Ă  tout le monde. Le mĂ©canisme d'enregistrement de nouvelles propriĂ©tĂ©s est « Examen par un expert » (RFC 8126) et les propriĂ©tĂ©s sont dans un registre IANA.

Passons maintenant Ă  un aspect compliquĂ© mais indispensable des calendriers : les rĂšgles de rĂ©currence, comme « RĂ©union de service tous les premiers lundis du mois Ă  10 h, sauf jour fĂ©rié ». Il est important de maintenir ces Ă©vĂšnements rĂ©currents sous forme de rĂšgles, et de ne pas de les instancier immĂ©diatement, car l'application des rĂšgles peut donner des rĂ©sultats diffĂ©rents dans le futur. JSCalendar permet une propriĂ©tĂ© recurrenceRules qui dĂ©crit ces rĂšgles de rĂ©currence et Ă©videmment une excludedRecurrenceRules car s'il n'y a pas d'exceptions, ce n'est pas drĂŽle. Exprimer les rĂšgles n'est pas facile. L'idĂ©e est de spĂ©cifier la rĂ©currence sous forme d'une sĂ©rie de rĂšgles, chacune indiquant une frĂ©quence (annuelle, mensuelle, etc), Ă  chaque fois Ă  partir de la propriĂ©tĂ© start, le calendrier utilisĂ© (qui doit ĂȘtre un des calendriers disponibles dans CLDR), la marche Ă  suivre quand une rĂšgle produit une date invalide dans ce calendrier (annuler l'Ă©vĂšnement, le mettre avant, le mettre aprĂšs), et plein d'autres propriĂ©tĂ©s optionnelles comme le jour du mois (« rĂ©union tous les 6 du mois »), de la semaine (« tous les mercredis »), etc. Il faut ensuite plusieurs pages au RFC pour expliquer la façon subtile dont les rĂšgles sont appliquĂ©es, et se combinent. Les exceptions de la excludedRecurrenceRules fonctionnent de la mĂȘme façon, et sont ensuite soustraites des dates-et-heures sĂ©lectionnĂ©es par les rĂšgles.

Le RFC fournit cet exemple de récurrence : le premier avril arrive tous les ans (et dure une journée, notez le duration) :

    {
     "...": "",
     "title": "April Fool's Day",
     "showWithoutTime": true,
     "start": "1900-04-01T00:00:00",
     "duration": "P1D",
     "recurrenceRules": [{
       "@type": "RecurrenceRule",
       "frequency": "yearly"
     }]
   }
  
Alors qu'ici, on fait du yoga une demi-heure chaque jour à 7 h du matin :
   {
     "...": "",
     "title": "Yoga",
     "start": "2020-01-01T07:00:00",
     "duration": "PT30M",
     "recurrenceRules": [{
       "@type": "RecurrenceRule",
       "frequency": "daily"
     }]
   }
  

Bon, ensuite, quelques dĂ©tails pour aider le logiciel Ă  classer et prĂ©senter les Ă©vĂšnements. Un Ă©vĂšnement peut avoir des propriĂ©tĂ©s comme priority (s'il y a deux rĂ©unions en mĂȘme temps, laquelle choisir ?), freeBusyStatus (est-ce que cet Ă©vĂšnement fait que je doive ĂȘtre considĂ©rĂ© comme occupĂ© ou est-il compatible avec autre chose ?), privacy (cet Ă©vĂšnement peut-il ĂȘtre affichĂ© publiquement ?), participationStatus (je viendrai, je ne viendrai pas, je ne sais pas encore
), et plein d'autres encore.

Il y a aussi des propriétés concernant d'autres sujets, par exemple l'adaptation locale. Ainsi, la propriété localizations indique la ou les langues à utiliser (leur valeur est une étiquette de langue du RFC 5646).

Toutes les propriétés vues jusqu'à présent étaient possibles pour tous les types d'objets JSCalendar (évÚnement, tùche et groupe). D'autres propriétés sont spécifiques à un ou deux types :

  • Les Ă©vĂšnements (Event) peuvent avoir entre autres un start (un LocalDateTime qui indique le dĂ©but de l'Ă©vĂšnement) et un duration (la durĂ©e de l'Ă©vĂšnement).
  • Les tĂąches (Task) peuvent avoir un start mais aussi un due qui indique la date oĂč elles doivent ĂȘtre terminĂ©es, et un percentComplete (pour les chefs de projet
).
  • Les groupes (Group) ont, par exemple, entries, qui indique les objets qui sont membres du groupe.

Les fichiers Ă  ce format JSCalendar sont servis sur l'Internet avec le type application/jscalendar+json.

Pour terminer, voyons un peu la sĂ©curitĂ© de JSCalendar (section 7). Évidemment, toutes les informations stockĂ©es dans un calendrier sont sensibles : rares sont les personnes qui accepteraient de voir la totalitĂ© de leur agenda ĂȘtre publiĂ©e ! Celui-ci permet en effet de connaitre le graphe social (les gens qu'on connait), les lieux oĂč passe la personne, ses habitudes et horaires, bref, que des choses personnelles. Toute application qui manipule des donnĂ©es JSCalendar doit donc soigneusement veiller Ă  la confidentialitĂ© de ces donnĂ©es, et doit les protĂ©ger.

Le risque d'accĂšs en lecture n'est pas le seul, la modification non autorisĂ©e de l'agenda serait Ă©galement un problĂšme, elle pourrait permettre, par exemple, de faire dĂ©placer une personne en un lieu donnĂ©. D'autres consĂ©quences d'une modification pourraient toucher la facturation (location d'une salle pendant une certaine durĂ©e) ou d'autres questions de sĂ©curitĂ© (activer ou dĂ©sactiver une alarme Ă  certains moments). L'application qui manie du JSCalendar doit donc Ă©galement empĂȘcher ces changements non autorisĂ©s.

Notez que ces problÚmes de sécurité ne concernent pas le format à proprement parler, mais les applications qui utilisent ce format. Rien dans JSCalendar, dans ce RFC, ne le rend particuliÚrement vulnérable ou au contraire protégé, tout est dans l'application.

Les rĂšgles de rĂ©currence sont complexes et, comme tout programme, elles peuvent entrainer des consĂ©quences imprĂ©vues, avec consommation de ressources informatiques associĂ©es. Un exemple aussi simple que la session de yoga quotidienne citĂ©e plus haut pourrait gĂ©nĂ©rer une infinitĂ© d'Ă©vĂšnements, si elle Ă©tait mise en Ɠuvre par une rĂ©pĂ©tition systĂ©matique, jusqu'Ă  la fin des temps. Les programmes doivent donc faire attention lorsqu'ils Ă©valuent les rĂšgles de rĂ©currence.

L'un des buts d'un format standard d'Ă©vĂšnements est Ă©videmment l'Ă©change de donnĂ©es. Il est donc normal et attendu qu'une application de gestion d'agenda reçoive des objets JSCalendar de l'extĂ©rieur, notamment via l'Internet. On voit souvent du iCalendar en piĂšce jointe d'un courrier, par exemple. Il ne faut pas faire une confiance aveugle Ă  ces donnĂ©es venues d'on ne sait oĂč, et ne pas tout intĂ©grer dans le calendrier du propriĂ©taire. L'authentification du courrier (par exemple avec DKIM, RFC 6376) aide un peu, mais n'est pas suffisante.

Les fuseaux horaires sont une source de confusion sans fin. Un utilisateur qui n'est pas attentif, lorsqu'on lui dit qu'un Ă©vĂšnement a lieu Ă  10h30 (UTC-5) peut croire que c'est 10h30 de son fuseau horaire Ă  lui. (Et encore, ici, j'ai indiquĂ© le fuseau horaire de maniĂšre lisible, contrairement Ă  ce que font la plupart des Étatsuniens, qui utilisent leurs sigles Ă  eux comme PST, ou ce que font les Français qui n'indiquent pas le fuseau horaire, persuadĂ©s qu'ils sont que le monde entier est Ă  l'heure de Paris.) Cette confusion peut ĂȘtre exploitĂ©e par des mĂ©chants qui utiliseraient les fuseaux horaires de maniĂšre dĂ©libĂ©rement peu claire pour tromper quelqu'un sur l'heure d'un Ă©vĂšnement. (Dans la sĂ©rie Mad Men, les hommes qui ne supportent pas l'arrivĂ©e d'une femme dans le groupe lui donnent des informations trompeuses sur les heures de rĂ©union, pour qu'elle manque ces Ă©vĂšnements.)

OĂč trouve-t-on du JSCalendar Ă  l'heure actuelle ? Mobilizon ne l'a pas encore (l'action « Ajouter Ă  mon agenda » exporte du iCalendar). Fastmail annonce qu'ils gĂšrent JSCalendar (mais apparemment seulement dans les Ă©changes JMAP, pas avec l'import/export normal). Cyrus l'a aussi (si vous avez des dĂ©tails, ça m'intĂ©resse). Pour le cas des rĂ©currences, vous avez une intĂ©ressante mise en Ɠuvre en Python. Attention, il y a aussi plein de logiciels qui s'appellent « jscalendar » (notamment des widgets JavaScript pour afficher un calendrier dans un formulaire Web) mais qui n'ont aucun rapport avec ce RFC.

RFC 9065: Considerations around Transport Header Confidentiality, Network Operations, and the Evolution of Internet Transport Protocols

La couche Transport n'est pas celle qui suscite le plus de passions dans l'Internet. Mais la récente normalisation du protocole QUIC a mis cette couche en avant et l'usage du chiffrement par QUIC a relancé le débat : quelles sont les conséquences d'un chiffrement de plus en plus poussé de la couche Transport ?

Traditionnellement, la couche Transport ne faisait pas de chiffrement (cf. RFC 8095 et RFC 8922). On chiffrait en-dessous (IPsec) ou au-dessus (TLS, SSH). IPsec ayant été peu déployé, l'essentiel du chiffrement aujourd'hui sur l'Internet est fait par TLS. Toute la mécanique TCP est donc visible aux routeurs sur le réseau. Ils peuvent ainsi mesurer le RTT, découvrir début et fin d'une connexion, et interférer avec celle-ci, par exemple en envoyant des paquets RST (ReSeT) pour mettre fin à la session. Cela permet de violer la vie privée (RFC 6973), par exemple en identifiant une personne à partir de son activité en ligne. Et cette visibilité de la couche Transport pousse à l'ossification : de nombreux intermédiaires examinent TCP et, si des options inhabituelles sont utilisées, bloquent les paquets. Pour éviter cela, QUIC chiffre une grande partie de la couche 4, pour éviter les interférences par les intermédiaires et pour défendre le principe de bout en bout et la neutralité du réseau. Comme souvent en sécurité, cette bonne mesure de protection a aussi des inconvénients, que ce RFC examine. Notons tout de suite que ce qui est un inconvénient pour les uns ne l'est pas forcément pour les autres : pour un FAI, ne pas pouvoir couper les connexions TCP de BitTorrent avec RST est un inconvénient mais, pour l'utilisateur, c'est un avantage, cela le protÚge contre certaines attaques par déni de service.

On ne peut pas sérieusement aujourd'hui utiliser des communications non-chiffrées (RFC 7258). Personne n'ose dire publiquement le contraire. Par contre, on entend souvent un discours « je suis pour le chiffrement, mais » et, comme toujours avec ce genre de phrase, c'est ce qui est aprÚs le « mais » qui compte. Ce RFC essaie de documenter les avantages et les inconvénients du chiffrement de la couche Transport, mais, en pratique, est plus détaillé sur les inconvénients, ce qui était déjà le cas du RFC 8404.

La section 2 du RFC explique quel usage peut ĂȘtre fait des informations de la couche Transport par les Ă©quipements intermĂ©diaires. En thĂ©orie, dans un modĂšle en couches idĂ©al, il n'y en aurait aucun : la couche Transport est de bout en bout, les routeurs et autres Ă©quipements intermĂ©diaires ne regardent rien au-dessus de la couche RĂ©seau. Mais en pratique, ce n'est pas le cas, comme l'explique cette section. (Question pour mes lecteurices au passage : vous semble-t-il lĂ©gitime de parler de DPI quand un routeur regarde le contenu de la couche Transport, dont il n'a en thĂ©orie pas besoin, ou bien doit-on rĂ©server ce terme aux cas oĂč il regarde dans la couche Application ?)

PremiĂšre utilisation de la couche Transport par des intermĂ©diaires : identifier des flots de donnĂ©es (une suite d'octets qui « vont ensemble »). Pourquoi en a-t-on besoin ? Il y a plusieurs raisons possibles, par exemple pour la rĂ©partition de charge, oĂč on veut envoyer tous les paquets d'un flot donnĂ© au mĂȘme serveur. Cela se fait souvent en prenant un tuple d'informations dans le paquet (tuple qui peut inclure une partie de la couche Transport, comme les ports source et destination) et en le condensant pour avoir un identificateur du flot. Si la couche Transport est partiellement ou totalement chiffrĂ©e, on ne pourra pas distinguer deux flots diffĂ©rents entre deux machines. En IPv6, l'Ă©tiquette de flot (RFC 6437) est une solution possible (RFC 6438, RFC 7098), mais je n'ai pas l'impression qu'elle soit trĂšs utilisĂ©e.

Maintenant, passons Ă  la question de l'identification d'un flot. Était-ce un transfert de fichiers, de la vidĂ©o, une session interactive ? Il faut dĂ©duire cette identification Ă  partir des informations de la couche Transport (voir le RFC 8558). Mais pourquoi identifier ces flots alors que l'opĂ©rateur doit tous les traiter pareil, en application du principe de neutralité ? Cela peut ĂȘtre dans l'intĂ©rĂȘt de l'utilisateur (mais le RFC ne donne pas d'exemple
) ou bien contre lui, par exemple Ă  des fins de surveillance, ou bien pour discriminer certains usages (comme le rĂ©clament rĂ©guliĂšrement certains politiciens et certains opĂ©rateurs), voire pour les bloquer complĂštement. Autrefois, on pouvait souvent identifier un service uniquement avec le numĂ©ro de port (43 pour whois, 25 pour le courrier, etc, cf. RFC 7605) mais cela n'a jamais marchĂ© parfaitement, plusieurs services pouvant utiliser le mĂȘme port et un mĂȘme service pouvant utiliser divers ports. De toute façon, cette identification par le numĂ©ro de port est maintenant finie, en partie justement en raison de cette discrimination selon les usages, qui pousse tout le monde Ă  tout faire passer sur le port 443. Certains services ont un moyen simple d'ĂȘtre identifiĂ©, par exemple par un nombre magique, volontairement placĂ© dans les donnĂ©es pour permettre l'identification, ou bien simple consĂ©quence d'une donnĂ©e fixe Ă  un endroit connu (RFC 3261, RFC 8837, RFC 7983
). Lors de la normalisation de QUIC, un dĂ©bat avait eu lieu sur la pertinence d'un nombre magique permettant d'identifier du QUIC, idĂ©e finalement abandonnĂ©e.

Si les Ă©quipements intermĂ©diaires indiscrets n'arrivent pas Ă  dĂ©terminer le service utilisĂ©, le flot va ĂȘtre considĂ©rĂ© comme inconnu et le RFC reconnait que certains opĂ©rateurs, en violation de la neutralitĂ© de l'Internet, ralentissent ces flots inconnus.

L'Ă©tape suivante pour ceux qui veulent identifier Ă  quoi servent les donnĂ©es qu'ils voient passer est d'utiliser des heuristiques. Ainsi, une visio-confĂ©rence Ă  deux fera sans doute passer Ă  peu prĂšs autant d'octets dans chaque sens, alors que regarder de la vidĂ©o Ă  la demande crĂ©era un trafic trĂšs asymĂ©trique. Des petits paquets UDP rĂ©guliĂšrement espacĂ©s permettent de soupçonner du trafic audio, mĂȘme si on n'a pas pu lire l'information SDP (RFC 4566). Des heuristiques plus subtiles peuvent permettre d'en savoir plus. Donc, il faut se rappeler que le chiffrement ne dissimule pas tout, il reste une vue qui peut ĂȘtre plus ou moins prĂ©cise (le RFC 8546 dĂ©crit en dĂ©tail cette notion de vue depuis le rĂ©seau).

Autre motivation pour analyser la couche Transport, l'amĂ©lioration des performances. Inutile de dire que le FAI typique ne va pas se pencher sur les problĂšmes de performance d'un abonnĂ© individuel (si ça rame avec Netflix, appeler le support de son FAI ne dĂ©clenche pas de recherches sĂ©rieuses). Mais cela peut ĂȘtre fait pour des analyse globales. LĂ  encore, les consĂ©quences peuvent ĂȘtre dans l'intĂ©rĂȘt de l'utilisateur, ou bien contre lui. Le RFC note que les mesures de performance peuvent amener Ă  une discrimination de certains services (« QoS », qualitĂ© de service, c'est-Ă -dire dĂ©gradation de certains services). Que peut-on mesurer ainsi, qui a un impact sur les performances ? Il y a la perte de paquets, qu'on peut dĂ©duire, en TCP, des retransmissions. Dans l'Internet, il y a de nombreuses causes de pertes de paquets, du parasite sur un lien radio Ă  l'abandon dĂ©libĂ©rĂ© par un routeur surchargĂ© (RFC 7567) en passant par des choix politiques de dĂ©favoriser certains paquets (RFC 2475). L'Ă©tude de ces pertes peut permettre dans certains cas de remonter aux causes.

On peut aussi mesurer le débit. Bon, c'est facile, sans la couche Transport, uniquement en regardant le nombre d'octets qui passent par les interfaces réseaux. Mais l'accÚs aux données de la couche Transport permet de séparer le débit total du débit utile (goodput, en anglais, pour le différencier du débit brut, le throughput, cf. section 2.5 du RFC 7928, et le RFC 5166). Pour connaitre ce débit utile, il faut pouvoir reconnaitre les retransmissions (si un paquet est émis trois fois avant enfin d'atteindre le destinataire, il ne contribue qu'une fois au débit utile). Une retransmission peut se voir en observant les numéros de séquence en TCP (ou dans d'autres protocoles comme RTP).

La couche Transport peut aussi nous dire quelle est la latence. Cette information est cruciale pour Ă©valuer la qualitĂ© des sessions interactives, par exemple. Et elle influe beaucoup sur les calculs du protocole de couche 4. (Voir l'article « Internet Latency: A Survey of Techniques and their Merits ».) Comment mesure-t-on la latence ? Le plus simple est de regarder les accusĂ©s de rĂ©ception TCP et d'en dĂ©duire le RTT. Cela impose d'avoir accĂšs aux numĂ©ros de sĂ©quence. Dans TCP, ils sont en clair, mais QUIC les chiffre (d'oĂč l'ajout du spin bit).

D'autres métriques sont accessibles à un observateur qui regarde la couche Transport. C'est le cas de la gigue, qui se déduit des observations de la latence, ou du réordonnancement des paquets (un paquet qui part aprÚs un autre, mais arrive avant). L'interprétation de toutes ces mesures dépend évidemment du type de lien. Un lien radio (RFC 8462) a un comportement différent d'un lien filaire (par exemple, une perte de paquets n'est pas forcément due à la congestion, elle peut venir de parasites).

Le RFC note que la couche RĂ©seau, que les Ă©quipements intermĂ©diaires ont tout Ă  fait le droit de lire, c'est son rĂŽle, porte parfois des informations qui peuvent ĂȘtre utiles. En IPv4, ce sont les options dans l'en-tĂȘte (malheureusement souvent jetĂ©es par des pare-feux trop fascistes, cf. RFC 7126), en IPv6, les options sont aprĂšs l'en-tĂȘte de rĂ©seau, et une option, Hop-by-hop option est explicitement prĂ©vue pour ĂȘtre examinĂ©e par tous les routeurs intermĂ©diaires.

Outre les statistiques, l'analyse des donnĂ©es de la couche Transport peut aussi servir pour les opĂ©rations (voir aussi le RFC 8517), pour localiser un problĂšme, pour planifier l'avitaillement de nouvelles ressources rĂ©seau, pour vĂ©rifier qu'il n'y a pas de tricheurs qui essaient de grapiller une part plus importante de la capacitĂ©, au risque d'aggraver la congestion (RFC 2914). En effet, le bon fonctionnement de l'Internet dĂ©pend de chaque machine terminale. En cas de perte de paquets, signal probable de congestion, les machines terminales sont censĂ©es rĂ©Ă©mettre les paquets avec prudence, puisque les ressources rĂ©seau sont partagĂ©es. Mais une machine Ă©goĂŻste pourrait avoir plus que sa part de la capacitĂ©. Il peut donc ĂȘtre utile de surveiller ce qui se passe, afin d'attraper d'Ă©ventuels tricheurs, par exemple une mise en Ɠuvre de TCP qui ne suivrait pas les rĂšgles habituelles. (Si on utilise UDP, l'application doit faire cela elle-mĂȘme, cf. RFC 8085. Ainsi, pour RTP, comme pour TCP, un observateur extĂ©rieur peut savoir si les machines se comportent normalement ou bien essaient de tricher.)

Autre utilisation de l'observation de la couche Transport pour l'opĂ©rationnel, la sĂ©curitĂ©, par exemple la lutte contre les attaques par dĂ©ni de service, l'IDS et autres fonctions. Le RFC note que cela peut se faire en coopĂ©ration avec les machines terminales, si c'est fait dans l'intĂ©rĂȘt de l'utilisateur. Puisqu'on parle de machines terminales, puisque le chiffrement d'une partie de la couche Transport est susceptible d'affecter toutes les activitĂ©s citĂ©es plus haut, le RFC rappelle la solution Ă©vidente : demander la coopĂ©ration des machines terminales. Il y a en effet deux cas : soit les activitĂ©s d'observation de la couche Transport sont dans l'intĂ©rĂȘt des utilisateurs, et faites avec leur consentement, et dans ce cas la machine de l'utilisateur peut certainement coopĂ©rer, soit ces activitĂ©s se font contre l'utilisateur (discrimination contre une application qu'il utilise, par exemple), et dans ce cas le chiffrement est une rĂ©ponse logique Ă  cette attaque. Bien sĂ»r, c'est la thĂ©orie ; en pratique, certaines applications ne fournissent guĂšre d'informations et de moyens de dĂ©boguage. Les protocoles de transport qui chiffrent une bonne partie de leur fonctionnement peuvent aussi aider, en exposant dĂ©libĂ©rement des informations. C'est par exemple ce que fait QUIC avec son spin bit dĂ©jĂ  citĂ©, ou avec ses invariants documentĂ©s dans le RFC 8999.

Autre cas oĂč le chiffrement de la couche Transport peut interfĂ©rer avec certains usages, les rĂ©seaux d'objets contraints, disposant de peu de ressources (faible processeur, batterie qu'il ne faut pas vider trop vite, etc). Il arrive dans ce cas d'utiliser des relais qui interceptent la communication, bricolent dans la couche Transport puis retransmettent les donnĂ©es. Un exemple d'un tel bricolage est la compression des en-tĂȘtes, courante sur les liens Ă  trĂšs faible capacitĂ© (cf. RFC 2507, RFC 2508, le ROHC du RFC 5795, RFC 6846, le SCHC du RFC 8724, etc). Le chiffrement rend Ă©videmment cela difficile, les relais n'ayant plus accĂšs Ă  l'information. C'est par exemple pour cela que le RTP sĂ©curisĂ© du RFC 3711 authentifie l'en-tĂȘte mais ne le chiffre pas. (Je suis un peu sceptique sur cet argument : d'une part, les objets contraints ne vont pas forcĂ©ment utiliser des protocoles de transport chiffrĂ©s, qui peuvent ĂȘtre coĂ»teux, d'autre part un sous-produit du chiffrement est souvent la compression, ce qui rend inutile le travail des relais.)

Un dernier cas citĂ© par le RFC oĂč l'observation du fonctionnement de la couche Transport par les machines intermĂ©diaires est utile est celui de la vĂ©rification de SLA. Si un contrat ou un texte lĂ©gal prĂ©voit certaines caractĂ©ristiques pour le rĂ©seau, l'observation de la couche 4 (retransmission, RTT
) est un moyen d'observer sans avoir besoin d'impliquer les machines terminales. (Personnellement, je pense justement que ces vĂ©rifications devraient plutĂŽt se faire depuis les machines terminales, par exemple avec les sondes RIPE Atlas, les SamKnows, etc.)

La section 3 du RFC dĂ©crit un autre secteur qui est intĂ©ressĂ© par l'accĂšs aux donnĂ©es de transport, la recherche. Par exemple, concevoir de nouveaux protocoles doit s'appuyer sur des mesures faites sur les protocoles existants, pour comprendre leurs forces et leurs faiblesses. C'est possible avec un protocole comme TCP, oĂč l'observation passive permet, via notamment les numĂ©ros de sĂ©quence, de dĂ©couvrir le RTT et le taux de perte de paquets. (Passive : sans injecter de paquets dans le rĂ©seau. Voir le RFC 7799.) Mais ces mĂȘmes informations peuvent aussi servir contre l'utilisateur. MĂȘme s'il n'y a pas d'intention nĂ©faste (par exemple de discrimination contre certains usages), toute information qui est exposĂ©e peut conduire Ă  l'ossification, l'impossibilitĂ© de changer le protocole dans le futur. Une des motivations des protocoles chiffrĂ©s comme QUIC est en effet d'Ă©viter l'ossification : une middlebox ne pourra pas prendre de dĂ©cisions sur la base d'informations qu'elle n'a pas. QUIC affiche des donnĂ©es au rĂ©seau seulement s'il le veut (c'est le cas du spin bit). D'oĂč Ă©galement le choix dĂ©libĂ©rĂ© de graisser, c'est-Ă -dire de faire varier certaines informations pour Ă©viter que des programmeurs de middleboxes incompĂ©tents et/ou paresseux n'en dĂ©duisent que cette information ne change jamais (le graissage est dĂ©crit dans le RFC 8701).

La bonne solution pour rĂ©colter des donnĂ©es sans sacrifier la vie privĂ©e est, comme dit plus haut, de faire participer les extrĂ©mitĂ©s, les machines terminales, ce qu'on nomme en anglais le endpoint-based logging. Actuellement, malheureusement, les mĂ©canismes de dĂ©boguage ou de rĂ©colte d'information sur ces machines terminales sont trop rĂ©duits, mais des efforts sont en cours. Par exemple, pour QUIC, c'est la normalisation du format « qlog » d'enregistrement des informations vues par la couche Transport (Internet-Draft draft-ietf-quic-qlog-main-schem) ou bien le format Quic-Trace. Mais le RFC note que la participation des machines terminales ne suffit pas toujours, notamment si on veut dĂ©terminer oĂč, dans le rĂ©seau, se produit un problĂšme.

AprĂšs qu'on ait vu les utilisations qui sont faites de l'analyse de la couche Trnsport par les Ă©quipements intermĂ©diaires, la section 4 du RFC revient ensuite sur les motivations du chiffrement de cette couche. Pourquoi ne pas se contenter de ce que font TLS et SSH, qui chiffrent uniquement la couche Application ? L'une des premiĂšres raisons est d'empĂȘcher l'ossification, ce phĂ©nomĂšne qui fait qu'on ne peut plus faire Ă©voluer la couche Transport car de stupides Ă©quipements intermĂ©diaires, programmĂ©s avec les pieds par des ignorants qui ne lisent pas les RFC, rejettent les paquets lĂ©gaux mais qui ne correspondent pas Ă  ce que ces Ă©quipements attendaient. Ainsi, si un protocole de transport permet l'utilisation d'un octet dans l'en-tĂȘte, mais que cet octet est Ă  zĂ©ro la plupart du temps, on risque de voir des middleboxes qui jettent les paquets oĂč certains bits de ce champ sont Ă  un car « ce n'est pas normal ». Tout ce qui est observable risque de devenir ossifiĂ©, ne pouvant plus ĂȘtre modifiĂ© par la suite. Chiffrer permet de garantir que les Ă©quipements intermĂ©diaires ne vont pas regarder ce qui ne les regarde pas. Le RFC donne plusieurs exemples Ă©difiants des incroyables comportements de ces logiciels Ă©crits par des gens qui ne comprenaient qu'une partie d'un protocole :

  • Pendant le dĂ©veloppement de TLS 1.3 (qui mĂšnera au RFC 8446), il a fallu concevoir 1.3 de maniĂšre Ă  ce qu'il ressemble Ă  1.2, car certaines middleboxes rejettaient du TLS lĂ©gal, mais diffĂ©rent de ce qu'elles attendaient.
  • MPTCP (RFC 8684) a Ă©galement dĂ» ĂȘtre modifiĂ© pour tenir compte de boitiers intermĂ©diaires qui observaient le fonctionnement de la fenĂȘtre TCP et se permettaient de couper les connexions qui leur semblaient anormales.
  • D'une maniĂšre gĂ©nĂ©rale, tout protocole qui permet des options est confrontĂ© Ă  des middleboxes qui interfĂšrent dĂšs qu'on utilise des options nouvelles. C'est le cas par exemple de TCP Fast Open (RFC 7413).
  • Encore pire, si c'est possible, on a vu des Ă©quipements intermĂ©diaires qui changeaient les numĂ©ros de sĂ©quence TCP, ce qui cassait les accusĂ©s de rĂ©ception SACK (RFC 2018).
Il n'est donc pas Ă©tonnant que les concepteurs de protocole cherchent dĂ©sormais Ă  chiffrer au maximum, pour Ă©viter ces interfĂ©rences. Le RFC 8546 rappelle ainsi que c'est la vue depuis le rĂ©seau (wire image), c'est-Ă -dire ce que les Ă©quipements intermĂ©diaires peuvent observer, pas la spĂ©cification Ă©crite du protocole, qui dĂ©termine, dans le monde rĂ©el, ce qu'un intermĂ©diaire peut observer et modifier. Il faut donc rĂ©duire cette vue au strict minimum ; tout ce qui n'est pas chiffrĂ© risque fortement d'ĂȘtre ossifiĂ©, figĂ©. Et le RFC 8558 affirme lui qu'on ne doit montrer au rĂ©seau que ce qui doit ĂȘtre utilisĂ© par le rĂ©seau, le reste, qui ne le regarde pas, doit ĂȘtre dissimulĂ©.

Une autre motivation du chiffrement de la couche Transport est Ă©videmment de mieux protĂ©ger la vie privĂ©e (RFC 6973). L'ampleur de la surveillance massive (RFC 7624) est telle qu'il est crucial de gĂȘner cette surveillance le plus possible. Le RFC note qu'il n'y a pas que la surveillance passive, il y a aussi l'ajout de donnĂ©es dans le trafic, pour faciliter la surveillance. Du fait de cet « enrichissement », il peut ĂȘtre utile, quand un champ doit ĂȘtre observable (l'adresse IP de destination est un bon exemple), d'utiliser quand mĂȘme la cryptographie pour empĂȘcher ses modifications, via un mĂ©canisme d'authentification. C'est ce que fait TCP-AO (RFC 5925, mais qui semble peu dĂ©ployĂ©), et bien sĂ»r le service AH d'IPsec (RFC 4302).

Comme on le voit, il y a une tension, voire une lutte, entre les opérateurs réseau et les utilisateurs. On pourrait se dire que c'est dommage, qu'il vaudrait mieux que tout le monde travaille ensemble. Cela a été discuté à l'IETF, avec des expressions comme « un traité de paix entre machines terminales et boitiers intermédiaires ». Pour l'instant, cela n'a pas débouché sur des résultats concrets, en partie parce qu'il n'existe pas d'organisations représentatives qui pourraient négocier, signer et faire respecter un tel traité de paix. On en reste donc aux mesures unilatérales. Les machines terminales doivent chiffrer de plus en plus pour maintenir le principe de bout en bout. Comme dans tout conflit, il y a des dégùts collatéraux (le RFC 8922 en décrit certains). Le problÚme n'étant pas technique mais politique, il est probable qu'il va encore durer. La tendance va donc rester à chiffrer de plus en plus de choses.

À noter qu'une autre mĂ©thode que le chiffrement existe pour taper sur les doigts des boitiers intermĂ©diaires pĂ©nibles, qui se mĂȘlent de ce qui ne les regarde pas, et s'en mĂȘlent mal : c'est le graissage. Son principe est d'utiliser dĂ©libĂ©rĂ©ment toutes les options possibles du protocole, pour habituer les middleboxes Ă  voir ces variations. Le RFC 8701 en donne un exemple, pour le cas de TLS.

Déterminer ce qu'il faut chiffrer, ce qu'il faut authentifier, et ce qu'il vaut mieux laisser sans protection, autorisant l'observation et les modifications, n'est pas une tùche facile. Autrefois, tout était exposé parce qu'on avait moins de problÚmes avec les boitiers intermédiaires et que les solutions, comme le chiffrement, semblaient trop lourdes. Aujourd'hui qu'on a des solutions réalistes, on doit donc choisir ce qu'on montre ou pas. Le choix est donc désormais explicite (cf. RFC 8558).

Au passage, une façon possible d'exposer des informations qui peuvent ĂȘtre utiles aux engins intermĂ©diaires est via un en-tĂȘte d'extension. Par exemple en IPv6, l'en-tĂȘte Hop-by-hop (RFC 8200, section 4.3) est justement fait pour cela (voir un exemple dans le RFC 8250, quoiqu'avec un autre type d'en-tĂȘte). Toutefois, cet en-tĂȘte Hop-by-hop est clairement un Ă©chec : beaucoup de routeurs jettent les paquets qui le portent (RFC 7872), ou bien les traitent plus lentement que les paquets sans cette information. C'est encore pire si cet en-tĂȘte porte des nouvelles options, inconnues de certaines middleboxes, et c'est pour cela que le RFC 8200 dĂ©conseille (dans sa section 4.8) la crĂ©ation de nouvelles options Hop-by-hop.

Mais, bon, le plus important est de dĂ©cider quoi montrer, pas juste comment. Le RFC rappelle qu'il serait sympa d'exposer explicitement des informations comme le RTT ou le taux de pertes vu par les machines terminales, plutĂŽt que de laisser les machines intermĂ©diaires le calculer (ce qu'elles ne peuvent de toute façon plus faire en cas de chiffrement). Cela permettrait de dĂ©coupler l'information de haut niveau des dĂ©tails du format d'un protocole de transport. Pourquoi une machine terminale ferait-elle cela, au risque d'exposer des informations qu'on peut considĂ©rer comme privĂ©es ? Le RFC cite la possibilitĂ© d'obtenir un meilleur service, sans trop prĂ©ciser s'il s'agit de laisser les opĂ©rateurs offrir un traitement prĂ©fĂ©rentiel aux paquets portant cette information, ou bien si c'est dans l'espoir que l'information exposĂ©e serve Ă  l'opĂ©rateur pour amĂ©liorer son rĂ©seau. (Comme le note le RFC 8558, il y a aussi le risque que la machine terminale mente au rĂ©seau. Au moins, avec le chiffrement, les choses sont claires : « je refuse de donner cette information » est honnĂȘte.)

DerniĂšre note, cet ajout d'informations utiles pour l'OAM peut ĂȘtre faite par la machine terminale mais aussi (section 6 du RFC) par certains Ă©quipements intermĂ©diaires.

En conclusion ? La section 7 du RFC reprend et résume les points importants :

  • Le chiffrement et l'authentification dans la couche de Transport sont une bonne chose. Personne n'ose dire ouvertement qu'il faudrait rester Ă  des protocoles de transport non sĂ©curisĂ©s. C'est un point sur lequel le document a beaucoup Ă©voluĂ©. Dans les versions antĂ©rieures, comme le notait Christian Huitema, « Much of the draft reads like a lamentation of the horrible consequences of encrypting transport headers », reflĂ©tant unilatĂ©ralement le point de vue des opĂ©rateurs rĂ©seau, et des vendeurs de middleboxes. Une relecture par Christopher Wood au dĂ©but du projet avait dĂ©jĂ  pointĂ© ce problĂšme, notant que le document Ă©tait trĂšs anti-chiffrement. Cette question a, fort logiquement, Ă©tĂ© le principal point de discussion Ă  l'IETF.
  • Le RFC, officiellement, ne tranche pas sur la pertinence et l'Ă©thique des pratiques qu'il dĂ©crit, il explique juste ce qui se fait. (Le mĂȘme argument, que je trouve un peu hypocrite, avait Ă©tĂ© utilisĂ© pour le trĂšs contestable RFC 8404.)
  • Comme souvent en sĂ©curitĂ©, il n'y a pas de solution idĂ©ale, il faudra trouver un compromis, par exemple entre la vie privĂ©e et l'OAM. Le RFC cite le spin bit de QUIC, qui avait Ă©tĂ© trĂšs chaudement discutĂ©, comme un exemple de compromis, en tout cas par le sĂ©rieux de l'analyse de ses coĂ»ts et de ses bĂ©nĂ©fices.
  • Le RFC reconnait que tout ce qui est exposĂ© au rĂ©seau s'ossifiera et deviendra une spĂ©cification de fait, qu'on ne pourra plus changer. Qu'un protocole choisisse d'exposer beaucoup ou au contraire trĂšs peu, il doit de toute façon faire ce choix explicitement.
  • MĂȘme le chiffrement de la couche Transport ne cache pas tout, et les couches infĂ©rieures exposent toujours des mĂ©tadonnĂ©es. Un surveillant dĂ©terminĂ© n'est donc pas dĂ©sarmĂ©. (MĂȘme si des organisations comme Interpol prĂ©tendent que le chiffrement rend la police « aveugle ».)
  • Les opĂ©rationnels se sont habituĂ©s depuis longtemps Ă  disposer de certaines informations, que le chiffrement de la couche Transport peut rendre inutilisables. Il faudra donc changer certaines pratiques et certains outils, par exemple avec davantage de coopĂ©ration des machines terminales (sinon, les opĂ©rations seront affectĂ©es).
  • Le RFC rappelle aussi qu'il existe diffĂ©rents types de rĂ©seaux, et qui n'ont pas forcĂ©ment les mĂȘmes contraintes et les mĂȘmes buts. Entre le rĂ©seau d'une entreprise qui veut contrĂŽler tout ce que font les employĂ©s et le rĂ©seau d'un FAI qui doit respecter (en thĂ©orie
) le principe de neutralitĂ©, il n'est pas du tout sĂ»r qu'on puisse trouver des solutions qui plaisent Ă  tout le monde. (A priori, l'IETF travaille et normalise pour l'Internet ouvert, pas forcĂ©ment pour chaque rĂ©seau connectĂ© Ă  l'Internet avec ses rĂšgles spĂ©cifiques.)
  • L'Internet est un rĂ©seau partagĂ© et son bon fonctionnement dĂ©pend donc du respect de certaines rĂšgles par tous. Par exemple, un protocole de transport doit penser aux autres, en ne noyant pas le rĂ©seau sous les paquets de retransmission. Si un fournisseur de logiciels Ă©tait tentĂ© de dĂ©velopper un protocole de transport Ă©goĂŻste, qui tente d'obtenir plus que sa part de la capacitĂ© du rĂ©seau, la tricherie pourrait se dĂ©tecter en observant le fonctionnement de ce protocole. Le chiffrement de la couche Transport rend Ă©videmment la vĂ©rification plus complexe.
  • Le bon fonctionnement de l'Internet sur le long terme dĂ©pend Ă©galement d'une activitĂ© de recherche et dĂ©veloppement, qui s'appuie sur des mesures, que le chiffrement de la couche Transport peut gĂȘner. (C'est bien, de se prĂ©occuper des chercheurs.)

Ansible – when, retries, until module

July 20th 2021 at 11:44

Modules:

when =

retries =

until =

delegate_to =

When, retries and until module can control the behaviour of the returned outcome based on the response.

---
- hosts: all
  gather_facts: no
  connection: local

  tasks:
    - name: purposely fail
      shell: ping -c 3 {{ inventory_hostname }}
      register: ping_response
      until: ping_response is not failed
      retries: 3
      ignore_errors: yes

    - name: debug ping response
      debug:
        msg: "{{ ping_response }}"
      when: ping_response is not failed

The effect

[jdoe@centos8 cisco_csr1k]$ ansible-playbook a1-1_3.yml

PLAY [all] *

TASK [purposely fail]
changed: [csr1kv02]
changed: [c8kv02]
changed: [c8kv01]
changed: [csr1kv01]
FAILED – RETRYING: purposely fail (1 retries left).
FAILED – RETRYING: purposely fail (1 retries left).
FAILED – RETRYING: purposely fail (1 retries left).
FAILED – RETRYING: purposely fail (1 retries left).
fatal: [wlc01]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 wlc01”, “delta”: “0:00:03.061694”, “end”: “2021-07-20 19:43:37.585494”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.523800”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING wlc01 (192.168.0.241) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— wlc01 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms\npipe 3”, “stdout_lines”: [“PING wlc01 (192.168.0.241) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— wlc01 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms”, “pipe 3”]}

ignoring
fatal: [csr1kv03]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 csr1kv03”, “delta”: “0:00:03.103826”, “end”: “2021-07-20 19:43:37.777578”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.673752”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING csr1kv03 (192.168.0.183) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— csr1kv03 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2063ms\npipe 3”, “stdout_lines”: [“PING csr1kv03 (192.168.0.183) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— csr1kv03 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2063ms”, “pipe 3”]}

ignoring
fatal: [c8kv03]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 c8kv03”, “delta”: “0:00:03.060089”, “end”: “2021-07-20 19:43:37.776701”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.716612”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING c8kv03 (192.168.0.193) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— c8kv03 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms\npipe 3”, “stdout_lines”: [“PING c8kv03 (192.168.0.193) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— c8kv03 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2027ms”, “pipe 3”]}

ignoring
fatal: [wlc02]: FAILED! => {“attempts”: 1, “changed”: true, “cmd”: “ping -c 3 wlc02”, “delta”: “0:00:03.104390”, “end”: “2021-07-20 19:43:37.904509”, “msg”: “non-zero return code”, “rc”: 1, “start”: “2021-07-20 19:43:34.800119”, “stderr”: “”, “stderr_lines”: [], “stdout”: “PING wlc02 (192.168.0.242) 56(84) bytes of data.\nFrom centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable\nFrom centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable\n\n— wlc02 ping statistics —\n3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2071ms\npipe 3”, “stdout_lines”: [“PING wlc02 (192.168.0.242) 56(84) bytes of data.”, “From centos8 (192.168.0.252) icmp_seq=1 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=2 Destination Host Unreachable”, “From centos8 (192.168.0.252) icmp_seq=3 Destination Host Unreachable”, “”, “— wlc02 ping statistics —“, “3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2071ms”, “pipe 3”]}

ignoring

TASK [debug ping response] ***
ok: [csr1kv01] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 csr1kv01”,
“delta”: “0:00:02.072632”,
“end”: “2021-07-20 19:43:28.312930”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.240298”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING csr1kv01 (192.168.0.181) 56(84) bytes of data.\n64 bytes from csr1kv01 (192.168.0.181): icmp_seq=1 ttl=255 time=0.532 ms\n64 bytes from csr1kv01 (192.168.0.181): icmp_seq=2 ttl=255 time=0.599 ms\n64 bytes from csr1kv01 (192.168.0.181): icmp_seq=3 ttl=255 time=2.17 ms\n\n— csr1kv01 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2051ms\nrtt min/avg/max/mdev = 0.532/1.101/2.174/0.759 ms”,
“stdout_lines”: [
“PING csr1kv01 (192.168.0.181) 56(84) bytes of data.”,
“64 bytes from csr1kv01 (192.168.0.181): icmp_seq=1 ttl=255 time=0.532 ms”,
“64 bytes from csr1kv01 (192.168.0.181): icmp_seq=2 ttl=255 time=0.599 ms”,
“64 bytes from csr1kv01 (192.168.0.181): icmp_seq=3 ttl=255 time=2.17 ms”,
“”,
“— csr1kv01 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2051ms”,
“rtt min/avg/max/mdev = 0.532/1.101/2.174/0.759 ms”
]
}
}
skipping: [csr1kv03]
ok: [csr1kv02] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 csr1kv02”,
“delta”: “0:00:02.035590”,
“end”: “2021-07-20 19:43:28.238564”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.202974”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING csr1kv02 (192.168.0.182) 56(84) bytes of data.\n64 bytes from csr1kv02 (192.168.0.182): icmp_seq=1 ttl=255 time=0.607 ms\n64 bytes from csr1kv02 (192.168.0.182): icmp_seq=2 ttl=255 time=0.529 ms\n64 bytes from csr1kv02 (192.168.0.182): icmp_seq=3 ttl=255 time=0.540 ms\n\n— csr1kv02 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2006ms\nrtt min/avg/max/mdev = 0.529/0.558/0.607/0.043 ms”,
“stdout_lines”: [
“PING csr1kv02 (192.168.0.182) 56(84) bytes of data.”,
“64 bytes from csr1kv02 (192.168.0.182): icmp_seq=1 ttl=255 time=0.607 ms”,
“64 bytes from csr1kv02 (192.168.0.182): icmp_seq=2 ttl=255 time=0.529 ms”,
“64 bytes from csr1kv02 (192.168.0.182): icmp_seq=3 ttl=255 time=0.540 ms”,
“”,
“— csr1kv02 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2006ms”,
“rtt min/avg/max/mdev = 0.529/0.558/0.607/0.043 ms”
]
}
}
ok: [c8kv01] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 c8kv01”,
“delta”: “0:00:02.065711”,
“end”: “2021-07-20 19:43:28.302238”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.236527”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING c8kv01 (192.168.0.191) 56(84) bytes of data.\n64 bytes from c8kv01 (192.168.0.191): icmp_seq=1 ttl=255 time=0.235 ms\n64 bytes from c8kv01 (192.168.0.191): icmp_seq=2 ttl=255 time=0.197 ms\n64 bytes from c8kv01 (192.168.0.191): icmp_seq=3 ttl=255 time=0.291 ms\n\n— c8kv01 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2058ms\nrtt min/avg/max/mdev = 0.197/0.241/0.291/0.038 ms”,
“stdout_lines”: [
“PING c8kv01 (192.168.0.191) 56(84) bytes of data.”,
“64 bytes from c8kv01 (192.168.0.191): icmp_seq=1 ttl=255 time=0.235 ms”,
“64 bytes from c8kv01 (192.168.0.191): icmp_seq=2 ttl=255 time=0.197 ms”,
“64 bytes from c8kv01 (192.168.0.191): icmp_seq=3 ttl=255 time=0.291 ms”,
“”,
“— c8kv01 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2058ms”,
“rtt min/avg/max/mdev = 0.197/0.241/0.291/0.038 ms”
]
}
}
skipping: [c8kv03]
ok: [c8kv02] => {
“msg”: {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“attempts”: 1,
“changed”: true,
“cmd”: “ping -c 3 c8kv02”,
“delta”: “0:00:02.103911”,
“end”: “2021-07-20 19:43:28.302508”,
“failed”: false,
“rc”: 0,
“start”: “2021-07-20 19:43:26.198597”,
“stderr”: “”,
“stderr_lines”: [],
“stdout”: “PING c8kv02 (192.168.0.192) 56(84) bytes of data.\n64 bytes from c8kv02 (192.168.0.192): icmp_seq=1 ttl=255 time=0.289 ms\n64 bytes from c8kv02 (192.168.0.192): icmp_seq=2 ttl=255 time=0.206 ms\n64 bytes from c8kv02 (192.168.0.192): icmp_seq=3 ttl=255 time=0.220 ms\n\n— c8kv02 ping statistics —\n3 packets transmitted, 3 received, 0% packet loss, time 2065ms\nrtt min/avg/max/mdev = 0.206/0.238/0.289/0.038 ms”,
“stdout_lines”: [
“PING c8kv02 (192.168.0.192) 56(84) bytes of data.”,
“64 bytes from c8kv02 (192.168.0.192): icmp_seq=1 ttl=255 time=0.289 ms”,
“64 bytes from c8kv02 (192.168.0.192): icmp_seq=2 ttl=255 time=0.206 ms”,
“64 bytes from c8kv02 (192.168.0.192): icmp_seq=3 ttl=255 time=0.220 ms”,
“”,
“— c8kv02 ping statistics —“,
“3 packets transmitted, 3 received, 0% packet loss, time 2065ms”,
“rtt min/avg/max/mdev = 0.206/0.238/0.289/0.038 ms”
]
}
}
skipping: [wlc01]
skipping: [wlc02]

PLAY RECAP *
c8kv01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c8kv02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c8kv03 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
csr1kv01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
csr1kv02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
csr1kv03 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
wlc01 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1
wlc02 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=1

Ansible – Error handling by using block and rescue

July 20th 2021 at 09:42

While developing ansible automation code, I wanted to test the port 22 reachability. If any host is not reachable, then it will throw a Failed error and it gets classified as failed. When you use rescue, this error can be handled more gracefully. Here is how it is done.

I have 4 active hosts and 1 inactive host. When 1 inactive host throws an error, it should be handled by rescue module.

Ansible.cfg file

[defaults]
inventory=inventory
host_key_checking=False
#timeout = 30
nocows = 1
deprecation_warnings = False
retry_files_enabled = False
log_path = ./csr1k_ansible.log
forks = 30
interpreter_python=auto_silent
#ansible_python_interpreter: /usr/bin/python3
[persistent_connection]
command_timeout = 240

Inventory file

[ios:vars]
ansible_network_os=ios
ansible_user=cisco
ansible_password=K0ala123

[ios:children]
routers
switches

[routers]
csr1kv01 ansible_host=192.168.0.181
csr1kv02 ansible_host=192.168.0.182
csr1kv03 ansible_host=192.168.0.183   <<< This one is inactive

[switches]
c8kv01 ansible_host=192.168.0.191
c8kv02 ansible_host=192.168.0.192

The Original playbook

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
    - block:
        - wait_for_connection:
            sleep: 1
            timeout: 5


    - debug:
        msg: "{{ inventory_hostname }} is running"

Run the playbook

[jdoe@centos8 cisco_csr1k]$ ansible-playbook a1-1_2.yml

PLAY [all] ***********************************************************************************************************************************************************************************************************************

TASK [wait_for_connection] *******************************************************************************************************************************************************************************************************
ok: [c8kv01]
ok: [csr1kv01]
ok: [c8kv02]
ok: [csr1kv02]
fatal: [csr1kv03]: FAILED! => {"changed": false, "elapsed": 25, "msg": "timed out waiting for connection port up: [Errno None] Unable to connect to port 22 on 192.168.0.183"}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [c8kv01] => {
    "msg": "c8kv01 is running"
}
ok: [c8kv02] => {
    "msg": "c8kv02 is running"
}
ok: [csr1kv01] => {
    "msg": "csr1kv01 is running"
}
ok: [csr1kv02] => {
    "msg": "csr1kv02 is running"
}

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c8kv02                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv01                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv02                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv03                   : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Now, I want to change failed=1 to rescued=1.

Updated Playbook

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
    - block:
        - wait_for_connection:
            sleep: 1
            timeout: 5
      rescue:
        - debug:
            msg: "{{ inventory_hostname }} not connected. End of host."
        - meta: clear_host_errors
        - meta: end_host

    - debug:
        msg: "{{ inventory_hostname }} is running"

Run the playbook again

[jdoe@centos8 cisco_csr1k]$ ansible-playbook a1-1_2.yml

PLAY [all] ***********************************************************************************************************************************************************************************************************************

TASK [wait_for_connection] *******************************************************************************************************************************************************************************************************
ok: [csr1kv02]
ok: [c8kv01]
ok: [c8kv02]
ok: [csr1kv01]
fatal: [csr1kv03]: FAILED! => {"changed": false, "elapsed": 25, "msg": "timed out waiting for connection port up: [Errno None] Unable to connect to port 22 on 192.168.0.183"}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv03] => {
    "msg": "csr1kv03 not connected. End of host."
}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv01] => {
    "msg": "csr1kv01 is running"
}
ok: [c8kv01] => {
    "msg": "c8kv01 is running"
}
ok: [csr1kv02] => {
    "msg": "csr1kv02 is running"
}
ok: [c8kv02] => {
    "msg": "c8kv02 is running"
}

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c8kv02                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv01                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv02                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv03                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

Now the failed error message has been handled correctly and evrything is green.

Bonus: this is another communication test YAML script without the rescue option. Change the port number as required.

---
- hosts: all
  gather_facts: no
  connection: network_cli

  tasks:
    - name: Filter unreachable devices
      wait_for: host="{{ inventory_hostname }}" port=22 timeout=3
    - debug: msg="port 22 OK"

    - name: CHECK CURRENT VERSION
      ios_facts:

    - debug:
        msg:
        - 'Current version is {{ ansible_net_version }}'
PLAY [all] ***********************************************************************************************************************************************************************************************************************

TASK [Filter unreachable devices] ************************************************************************************************************************************************************************************************
ok: [csr1kv02]
ok: [c8kv01]
ok: [csr1kv01]
ok: [c8kv02]
fatal: [csr1kv03]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": false, "elapsed": 2, "msg": "Timeout when waiting for csr1kv03:22"}

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv02] => {
    "msg": "port 22 OK"
}
ok: [c8kv01] => {
    "msg": "port 22 OK"
}
ok: [csr1kv01] => {
    "msg": "port 22 OK"
}
ok: [c8kv02] => {
    "msg": "port 22 OK"
}

TASK [CHECK CURRENT VERSION] *****************************************************************************************************************************************************************************************************
[WARNING]: default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards
ok: [c8kv01]
ok: [c8kv02]
ok: [csr1kv01]
ok: [csr1kv02]

TASK [debug] *********************************************************************************************************************************************************************************************************************
ok: [csr1kv01] => {
    "msg": [
        "Current version is 16.08.02"
    ]
}
ok: [csr1kv02] => {
    "msg": [
        "Current version is 16.08.02"
    ]
}
ok: [c8kv02] => {
    "msg": [
        "Current version is 17.04.01b"
    ]
}
ok: [c8kv01] => {
    "msg": [
        "Current version is 17.04.01b"
    ]
}

PLAY RECAP ***********************************************************************************************************************************************************************************************************************
c8kv01                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c8kv02                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv01                   : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv02                   : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
csr1kv03                   : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Cent OS 8 – Add SFTP service [2/2], install nmap on Ubuntu 20 to scan port and test SFTP

July 20th 2021 at 02:48

This is the continuation of the previous post. Here, we will install the nmap package to another Linux server (192.168.0.251) and test the open ports on the SFTP server, a router and a switch.

Check nmap package

jdoe@u20s:~$ sudo apt list nmap
[sudo] password for jdoe: **********
Listing
 Done
nmap/focal 7.80+dfsg1-2build1 amd64

# Install nmap

jdoe@u20s:~$ sudo apt install nmap -y
Reading package lists
 Done
Building dependency tree
Reading state information
 Done
The following packages were automatically installed and are no longer required:
ieee-data python3-argcomplete python3-dnspython python3-jmespath
python3-kerberos python3-libcloud python3-lockfile python3-netaddr
python3-ntlm-auth python3-requests-kerberos python3-requests-ntlm
python3-selinux python3-winrm python3-xmltodict squashfs-tools tcpd

 [ommitted for brevity]
Processing triggers for man-db (2.9.1-1) 

Processing triggers for libc-bin (2.31-0ubuntu9.2) 


jdoe@u20s:~$ nmap –version
Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1d nmap-libssh2-1.8.2 libz-1.2.11 libpcre-8.39 libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

Run nmap against another Linux server

jdoe@u20s:~$ sudo nmap -n 192.168.0.252 <<< Red Hat (CentOS) Linux IP
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-20 00:22 UTC
Nmap scan report for 192.168.0.252
Host is up (0.00013s latency).
Not shown: 968 filtered ports, 28 closed ports
PORT STATE SERVICE
21/tcp open ftp <<< This port is used for FTP for vsftpd
22/tcp open ssh <<< Port is available for SFTP for Open SSH
80/tcp open http
443/tcp open https
MAC Address: 00:0C:29:BE:CA:A5 (VMware)

Run nmap against a Cisco router

jdoe@u20s:~$ sudo nmap -n 192.168.0.181 <<< Cisco router IP
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-20 00:26 UTC
Nmap scan report for 192.168.0.181
Host is up (0.00096s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
8090/tcp open opsmessaging
MAC Address: 00:0C:29:07:29:B5 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.67 seconds

Run nmap against a Cisco switch

jdoe@u20s:~$ sudo nmap -n 192.168.0.245 <<< Cisco switch IP
Starting Nmap 7.80 ( https://nmap.org ) at 2021-07-20 00:29 UTC
Nmap scan report for 192.168.0.245
Host is up (0.00082s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
MAC Address: 00:0C:29:0C:78:BF (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.72 seconds

Access SFTP server from another Linux server

jdoe@u20s:~$ sftp sftpuser@192.168.0.252
The authenticity of host ‘192.168.0.252 (192.168.0.252)’ can’t be established.
ECDSA key fingerprint is SHA256:UMZoyCaK2sMR2zEI9JAVRxFtSxbPhRwp1nnL77qKyfo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added ‘192.168.0.252’ (ECDSA) to the list of known hosts.

sftpuser@192.168.0.252’s password: **********
Connected to 192.168.0.252.
sftp> pwd
Remote working directory: /upload
sftp> dir -lh
-rw-r–r– ? 1003 1003 3.6M Jul 22 2020 4MB.bin
-rw-r–r– ? 0 0 10B Jul 19 07:02 sftptest999.txt

Get (download) a test file to your remote machine.

sftp> get sftptest999.txt
Fetching /upload/sftptest999.txt to sftptest999.txt
/upload/sftptest999.txt 100% 10 0.9KB/s 00:00
sftp> ^Z
[1]+ Stopped sftp sftpuser@192.168.0.252

jdoe@u20s:~$ ls -lh | grep sftp*
-rw-r–r– 1 jdoe jdoe 10 Jul 20 00:38 sftptest999.txt

You cannot ssh into this server.

jdoe@u20s:~$ ssh sftpuser@192.168.0.252
sftpuser@192.168.0.252’s password:
This service allows sftp connections only.
Connection to 192.168.0.252 closed.

Source: https://www.howtoforge.com/tutorial/how-to-setup-an-sftp-server-on-centos/

Cent OS 8 – Add SFTP service [1/2]

July 19th 2021 at 09:25

Note: Assumption, it is assumed that you already have vsftpd and open ssh server installed.

SFTP need to be configured using SSH server.

Add a new group for sftpusers, here I am using the group name as sftpusers

[jdoe@centos8 cisco_csr1k]$ sudo groupadd sftpusers

Try to crete a new user and add to this group, since I have an existing user, I will delete the user and recreat it.

[jdoe@centos8 cisco_csr1k]$ sudo useradd -g sftpusers -d /upload -s /sbin/nologin sftpuser
useradd: user ‘sftpuser’ already exists

Since the user is hogging a process, I need to kill it using the kill -9 command

[jdoe@centos8 cisco_csr1k]$ sudo userdel -r sftpuser
userdel: user sftpuser is currently used by process 21383
[jdoe@centos8 cisco_csr1k]$ sudo kill -9 21383
[jdoe@centos8 cisco_csr1k]$ sudo userdel -r sftpuser

Recreate the user for sftp upload/download

[jdoe@centos8 cisco_csr1k]$ sudo useradd -g sftpusers -d /upload -s /sbin/nologin sftpuser
[jdoe@centos8 cisco_csr1k]$ sudo passwd sftpuser
Changing password for user sftpuser.
New password: Retype new password:
passwd: all authentication tokens updated successfully.

Make SFTP directory. Here create a root directory called upload and this is where all the files will be placed.

[jdoe@centos8 /]$ pwd
/
[jdoe@centos8 /]$ sudo mkdir -p /data/sftp
[jdoe@centos8 /]$ sudo chmod 705 /data

[jdoe@centos8 /]$ sudo mkdir -p /data/sftpuser/upload
[jdoe@centos8 /]$ sudo chown -R root:sftpusers /data/sftpuser
[jdoe@centos8 /]$ sudo chown -R sftpuser:sftpusers /data/sftpuser/upload

[jdoe@centos8 /]$ ls -ld /data
drwx—r-x. 4 root root 34 Jul 19 16:54 /data
[jdoe@centos8 /]$ ls -ld /data/sftpuser
drwxr-xr-x. 3 root sftpusers 20 Jul 19 16:54 /data/sftpuser
[jdoe@centos8 /]$ ls -ld /data/sftpuser/upload
drwxr-xr-x. 2 sftpuser sftpusers 6 Jul 19 16:54 /data/sftpuser/upload
[jdoe@centos8 /]$ sudo nano /etc/ssh/sshd_config

Go to /etc/ssh/sshd_config and add the following lines at the end.

[jdoe@centos8 /]$ nano /etc/ssh/sshd_config



Match Group sftpusers
ChrootDirectory /data/%u
ForceCommand internal-sftp

Restart SSHD service

[jdoe@centos8 /]$ service sshd restart
Redirecting to /bin/systemctl restart sshd.service
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to restart ‘sshd.service’.
Authenticating as: John Doe (jdoe)
Password:
==== AUTHENTICATION COMPLETE ====

Check SSHD service

[jdoe@centos8 /]$ service sshd status
Redirecting to /bin/systemctl status sshd.service
● sshd.service – OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-07-19 16:58:27 AEST; 2s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 23475 (sshd)
Tasks: 1 (limit: 23532)
Memory: 1.1M
CGroup: /system.slice/sshd.service
└─23475 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc -oMACs=hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh>

Jul 19 16:58:27 centos8 systemd[1]: Stopped OpenSSH server daemon.
Jul 19 16:58:27 centos8 systemd[1]: Starting OpenSSH server daemon

Jul 19 16:58:27 centos8 sshd[23475]: Server listening on 0.0.0.0 port 22.
Jul 19 16:58:27 centos8 sshd[23475]: Server listening on :: port 22.
Jul 19 16:58:27 centos8 systemd[1]: Started OpenSSH server daemon.

Create or add test files

[jdoe@centos8 /]$ sudo touch /data/sftpuser/upload/sftptest999.txt
[jdoe@centos8 /]$ ls /data/sftpuser/upload/ -lh
total 3.6M
-rw-r–r–. 1 sftpuser sftpusers 3.6M Jul 22 2020 4MB.bin
-rw-r–r–. 1 root root 10 Jul 19 17:02 sftptest999.txt

============================

Verification

c9800-cl#copy sftp://sftpuser:K0ala123@192.168.0.252/sftptest999.txt flash:/sftptest999.txt
Destination filename [sftptest999.txt]?
0 bytes copied in 0.285 secs (0 bytes/sec)

c9800-cl#$K0ala123@192.168.0.252/4MB.bin flash:/sftptest_4MB.bin
Destination filename [sftptest_4MB.bin]?
!!!!!!!!!!!!!!!!!!!!
3752704 bytes copied in 3.467 secs (1082407 bytes/sec)

c9800-cl#
c9800-cl#dir | in sftptest
23 -rw- 10 Jul 19 2021 18:03:29 +00:00 sftptest999.txt
24 -rw- 3752704 Jul 19 2021 18:07:24 +00:00 sftptest_4MB.bin

This is the debug of file transfer on Cisco device.

Jul 19 18:03:29.243:  SFTP rcv_stub: buffsize (140694477057376) verbose (0) filename (sftptest999.txt)
Jul 19 18:03:29.243: SFTP rcv: Starting download procedure for sftptest999.txt with buf_size (8192)
Jul 19 18:03:29.243: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_INIT bytes req (9) written (9)
Jul 19 18:03:29.246: SFTP get_string: msg_size = 179 length = 4096
Jul 19 18:03:29.246: SFTP: [54291 <- 192.168.0.252:22] recv SFTP do_init: Remote server version: 3
Jul 19 18:03:29.246: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_REALPATH for .
Jul 19 18:03:29.249: SFTP get_string: msg_size = 35 length = 4096
Jul 19 18:03:29.249: SFTP: [54291 <- 192.168.0.252:22] recv SFTP do_realpath: record count (1)
Jul 19 18:03:29.249: SFTP: [54291 -> 192.168.0.252:22] send SFTP rcv: Looking up /upload/sftptest999.txt
Jul 19 18:03:29.249: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_STAT for /upload/sftptest999.txt
Jul 19 18:03:29.250: SFTP get_string: msg_size = 37 length = 4096
Jul 19 18:03:29.250: SFTP: [54291 <- 192.168.0.252:22] recv SSH2_FXP_STAT attribs
Jul 19 18:03:29.250: SFTP rcv: file size (10) avail space (-1)
Jul 19 18:03:29.250: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_OPEN for /upload/sftptest999.txt (44)
Jul 19 18:03:29.251: SFTP get_string: msg_size = 13 length = 4096
Jul 19 18:03:29.251: SFTP rcv: Start fetching /upload/sftptest999.txt .

Jul 19 18:03:29.251: SFTP: [54291 -> 192.168.0.252:22] send SFTP rcv: Request server to send (8162) bytes data
Jul 19 18:03:29.251: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_READ bytes req (29) written (29)
Jul 19 18:03:29.252: SFTP get_string: msg_size = 19 length = 8192
Jul 19 18:03:29.252: SFTP fioctl: rcvd req 5
Jul 19 18:03:29.253: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_READ bytes req (29) written (29)
Jul 19 18:03:29.253: SFTP get_string: msg_size = 28 length = 8192
Jul 19 18:03:29.253: SFTP: [54291 <- 192.168.0.252:22] recv SFTP rcv: SSH2_FX_EOF
Jul 19 18:03:29.254: SFTP: [54291 <- 192.168.0.252:22] recv SFTP rcv: 10 bytes
Jul 19 18:03:29.254: SFTP: [54291 -> 192.168.0.252:22] send SSH2_FXP_CLOSE
Jul 19 18:03:29.255: SFTP get_string: msg_size = 24 length = 4096
Jul 19 18:03:29.256: SFTP fioctl: rcvd req 3
Jul 19 18:03:29.256: SFTP ifs_close: Read Operation

Source: https://www.howtoforge.com/tutorial/how-to-setup-an-sftp-server-on-centos/

Cisco 9800 WLC – Installation

July 16th 2021 at 05:47

Finished AireOS upgrade automation and now the work expect me to automate the newer Cisco 9800 WLC EWC upgrade. In the production we have Cisco 9120AXI model of Access Points, they support both CAPWAP and EWC mode. The APs work as a normal AP with CAPWAP mode and registers to a centralized WLC like the real Cisco 9800 WLC or the virtual WLC which we are installing here. If the AP is running in EWC, it basically runs a virtual machine version of Cisco 9800 WLC on the Cisco 9105/9120/9130Axx model of Access Points and works as both a WLC and AP, just like the cheap Netgear all-in-one wireless modems. Cisco 9800 WLCs are using the same codes as IOS-XE to keep them inline with the rest of Cisco fleet. I need to set up an environment quickly so I can start writing the automation codes.

Prep: Go to http://www.cisco.com with your smartnet credentials and download the following file. As I am developing automated upgrading codes, I need to start from an older C9800 codes and move up. Downloading 16.12.04a Gibraltar.

Required file name: C9800-CL-universalk9.16.12.04a.ova

Source: fowing a really good web site called Haifeng’s blog (www.lihaifeng.net)

Step 1: Log into ESXi

Step 2: Create a new VM

Step 3: Use the ova file downloaded from Cisco.com

Step 4: Give a name to your new WLC VM.

Step 5: Select the datastore

Step 6: Change the deployment option to 1K APs, 10K clients

Step 7: Click on ‘Finish’ to begin installation

Step 8: After about 10-15 minutes, you will be prompted with the first configuration screen. Here, answer ‘no’.

Step 9: Now follow the steps below to configure intigial configuration

9a. Go into enable mode first and configure SSH.

WLC>enable
WLC#config t
WLC(config)#line vty 0 15
WLC(config-line)#transport input ssh
WLC(config-line)#login local
WLC(config-line)#exit
WLC(config)#

9b. Configure hostname

WLC(config)#hostname c9800-cl
c9800-cl(config)#ip domain name italchemy.local
c9800-cl(config)#ip ssh version 2
c9800-cl(config)#crypto key generate rsa
The name for the keys will be: c9800-cl.italchemy.local
Choose the size of the key modulus in the range of 512 to 4096 for your
  General Purpose Keys. Choosing a key modulus greater than 512 may take
  a few minutes.
How many bits in the modulus [1024]: 1024
% Generating 1024 bit RSA keys, keys will be non-exportable...
[OK] (elapsed time was 0 seconds)
*Jul 16 11:18:11.622: %CRYPTO_ENGINE-5-KEY_ADDITION: A key named c9800-cl.italchemy.local has been generated or imported by crypto-engine

9c. Configure IP Addres using Gi1, (optionally you can configure this using vlan on the router)

c9800-cl(config)#interface gigabitEthernet1
c9800-cl(config)#no switchport
c9800-cl(config-interface)#ip add 192.168.0.251 255.255.255.0
c9800-cl(config-interface)#negotiation auto
c9800-cl(config-interface)#no mop enabled
c9800-cl(config-interface)#no mop sysid
c9800-cl(config)#exit
c9800-cl(config)#ip route 0.0.0.0 0.0.0.0 192.168.0.1
c9800-cl(config)#exit

9d. Configure username:

c9800-cl(config)#username wlcadmin privilege 15 secret SuperSecretPassword
c9800-cl(config)#exit
c9800-cl#write memory

9e. Check SSH login via Putty

9f. Now configure HTTPS for WEB Login and verify

c9800-cl#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
c9800-cl(config)#crypto key generate rsa modulus 2048 label web
The name for the keys will be: web

% The key modulus size is 2048 bits
% Generating 2048 bit RSA keys, keys will be non-exportable...
[OK] (elapsed time was 0 seconds)

c9800-cl(config)#ip http secure-server
c9800-cl(config)#ip http secure-trustpoint web
c9800-cl(config)#crypto pki trustpoint web
c9800-cl(ca-trustpoint)#enrollment selfsigned
c9800-cl(ca-trustpoint)#rsakeypair web
c9800-cl(ca-trustpoint)#exit
c9800-cl(config)#crypto pki enroll web
The router has already generated a Self Signed Certificate for
trustpoint TP-self-signed-4254639649.
If you continue the existing trustpoint and Self Signed Certificate
will be deleted.

Do you want to continue generating a new Self Signed Certificate? [yes/no]: yes
% Include the router serial number in the subject name? [yes/no]: yes
% Include an IP address in the subject name? [no]: yes
Enter Interface name or IP Address[]: 192.168.0.251
Generate Self Signed Router Certificate? [yes/no]: yes

Router Self Signed Certificate successfully created
c9800-cl(config)#ip http authentication local (optional, if you run into %WEBSERVER-5-LOGIN_FAILED)

9g. Configure country code

c9800-cl(config)#ap country AU
% 802.11bg/802.11a  Network must be disabled
c9800-cl(config)#ap dot11 24ghz shutdown
Disabling the 802.11b network may strand mesh APs.
Are you sure you want to continue? (y/n)[y]: y
c9800-cl(config)#ap dot11 5 shutdown
Disabling the 802.11a network may strand mesh APs.
Are you sure you want to continue? (y/n)[y]: y
c9800-cl(config)#ap country AU
Changing country code could reset channel and RRM grouping configuration. If running in RRM One-Time mode, reassign channels after this command. Check customized APs for valid channel values after this command.
Are you sure you want to continue? (y/n)[y]: y
c9800-cl(config)#no ap dot11 24ghz shutdown
c9800-cl(config)#no ap dot11 5 shutdown

9h. Wait for 3-5 minutes and log into the web gui (https://192.168.0.251/webui/)

Step 10: make sure you take a snapshot of the current state of the VM to have more joy out of this VM.

Now I am ready to write the automation scripts.

italchemy

Cisco 9800 WLC – Installation

July 16th 2021 at 05:47

Finished AireOS upgrade automation and now the work expect me to automate the newer Cisco 9800 WLC EWC upgrade. In the production we have Cisco 9120AXI model of Access Points, they support both CAPWAP and EWC mode. The APs work as a normal AP with CAPWAP mode and registers to a centralized WLC like the real Cisco 9800 WLC or the virtual WLC which we are installing here. If the AP is running in EWC, it basically runs a virtual machine version of Cisco 9800 WLC on the Cisco 9105/9120/9130Axx model of Access Points and works as both a WLC and AP, just like the cheap Netgear all-in-one wireless modems. Cisco 9800 WLCs are using the same codes as IOS-XE to keep them inline with the rest of Cisco fleet. I need to set up an environment quickly so I can start writing the automation codes.

Prep: Go to http://www.cisco.com with your smartnet credentials and download the following file. As I am developing automated upgrading codes, I need to start from an older C9800 codes and move up. Downloading 16.12.04a Gibraltar.

Required file name: C9800-CL-universalk9.16.12.04a.ova

Source: fowing a really good web site called Haifeng’s blog (www.lihaifeng.net)

Step 1: Log into ESXi

Step 2: Create a new VM

Step 3: Use the ova file downloaded from Cisco.com

Step 4: Give a name to your new WLC VM.

Step 5: Select the datastore

Step 6: Change the deployment option to 1K APs, 10K clients

Step 7: Click on ‘Finish’ to begin installation

Step 8: After about 10-15 minutes, you will be prompted with the first configuration screen. Here, answer ‘no’.

Step 9: Now follow the steps below to configure intigial configuration

9a. Go into enable mode first and configure SSH.

WLC>enable
WLC#config t
WLC(config)#line vty 0 15
WLC(config-line)#transport input ssh
WLC(config-line)#login local
WLC(config-line)#exit
WLC(config)#

9b. Configure hostname

WLC(config)#hostname c9800-cl
c9800-cl(config)#ip domain name italchemy.local
c9800-cl(config)#ip ssh version 2
c9800-cl(config)#crypto key generate rsa
The name for the keys will be: c9800-cl.italchemy.local
Choose the size of the key modulus in the range of 512 to 4096 for your
  General Purpose Keys. Choosing a key modulus greater than 512 may take
  a few minutes.
How many bits in the modulus [1024]: 1024
% Generating 1024 bit RSA keys, keys will be non-exportable...
[OK] (elapsed time was 0 seconds)
*Jul 16 11:18:11.622: %CRYPTO_ENGINE-5-KEY_ADDITION: A key named c9800-cl.italchemy.local has been generated or imported by crypto-engine

9c. Configure IP Addres using Gi1, (optionally you can configure this using vlan on the router)

c9800-cl(config)#interface gigabitEthernet1
c9800-cl(config)#no switchport
c9800-cl(config-interface)#ip add 192.168.0.251 255.255.255.0
c9800-cl(config-interface)#negotiation auto
c9800-cl(config-interface)#no mop enabled
c9800-cl(config-interface)#no mop sysid
c9800-cl(config)#exit
c9800-cl(config)#ip route 0.0.0.0 0.0.0.0 192.168.0.1
c9800-cl(config)#exit

9d. Configure username:

c9800-cl(config)#username wlcadmin privilege 15 secret SuperSecretPassword
c9800-cl(config)#exit
c9800-cl#write memory

9e. Check SSH login via Putty

9f. Now configure HTTPS for WEB Login and verify

c9800-cl#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
c9800-cl(config)#crypto key generate rsa modulus 2048 label web
The name for the keys will be: web

% The key modulus size is 2048 bits
% Generating 2048 bit RSA keys, keys will be non-exportable...
[OK] (elapsed time was 0 seconds)

c9800-cl(config)#ip http secure-server
c9800-cl(config)#ip http secure-trustpoint web
c9800-cl(config)#crypto pki trustpoint web
c9800-cl(ca-trustpoint)#enrollment selfsigned
c9800-cl(ca-trustpoint)#rsakeypair web
c9800-cl(ca-trustpoint)#exit
c9800-cl(config)#crypto pki enroll web
The router has already generated a Self Signed Certificate for
trustpoint TP-self-signed-4254639649.
If you continue the existing trustpoint and Self Signed Certificate
will be deleted.

Do you want to continue generating a new Self Signed Certificate? [yes/no]: yes
% Include the router serial number in the subject name? [yes/no]: yes
% Include an IP address in the subject name? [no]: yes
Enter Interface name or IP Address[]: 192.168.0.251
Generate Self Signed Router Certificate? [yes/no]: yes

Router Self Signed Certificate successfully created
c9800-cl(config)#ip http authentication local (optional, if you run into %WEBSERVER-5-LOGIN_FAILED)

9g. Configure country code

c9800-cl(config)#ap country AU
% 802.11bg/802.11a  Network must be disabled
c9800-cl(config)#ap dot11 24ghz shutdown
Disabling the 802.11b network may strand mesh APs.
Are you sure you want to continue? (y/n)[y]: y
c9800-cl(config)#ap dot11 5 shutdown
Disabling the 802.11a network may strand mesh APs.
Are you sure you want to continue? (y/n)[y]: y
c9800-cl(config)#ap country AU
Changing country code could reset channel and RRM grouping configuration. If running in RRM One-Time mode, reassign channels after this command. Check customized APs for valid channel values after this command.
Are you sure you want to continue? (y/n)[y]: y
c9800-cl(config)#no ap dot11 24ghz shutdown
c9800-cl(config)#no ap dot11 5 shutdown

9h. Wait for 3-5 minutes and log into the web gui (https://192.168.0.251/webui/)

Step 10: make sure you take a snapshot of the current state of the VM to have more joy out of this VM.

Now I am ready to write the automation scripts.

RFC 9063: Host Identity Protocol Architecture

Ce RFC propose d'aborder l'architecture de l'Internet en utilisant un nouveau type d'identificateur, le Host Identifier (HI), pour beaucoup d'usages qui sont actuellement ceux des adresses IP. Il remplace le RFC 4423, qui Ă©tait la description originale du protocole HIP, mais il n'y a pas de changements fondamentaux. HIP Ă©tait un projet trĂšs ambitieux mais, malgrĂ© ses qualitĂ©s, la disponibilitĂ© de plusieurs mises en Ɠuvre, et des annĂ©es d'expĂ©rimentation, il n'a pas percĂ©.

Une adresse IP sert actuellement à deux choses : désigner une machine (l'adresse IP sert par exemple à distinguer plusieurs connexions en cours) et indiquer comment la joindre (routabilité). Dans le premier rÎle, il est souhaitable que l'adresse soit relativement permanente, y compris en cas de changement de FAI ou de mobilité (actuellement, si une machine se déplace et change d'adresse IP, les connexions TCP en cours sont cassées). Dans le second cas, on souhaite au contraire une adresse qui soit le plus « physique » possible, le plus dépendante de la topologie. Ces deux demandes sont contradictoires.

HIP résout le problÚme en séparant les deux fonctions. Avec HIP, l'adresse IP ne serait plus qu'un identifiant « technique », ne servant qu'à joindre la machine, largement invisible à l'utilisateur et aux applications (un peu comme une adresse MAC aujourd'hui). Chaque machine aurait un HI (Host Identifier) unique. Contrairement aux adresses IP, il n'y a qu'un HI par machine multi-homée mais on peut avoir plusieurs HI pour une machine si cela correspond à des usages différents, par exemple une identité publique, et une « anonyme ».

Pour pouvoir ĂȘtre vĂ©rifiĂ©, le nouvel identificateur, le HI sera (dans la plupart des cas) une clĂ© publique cryptographique, qui sera peut-ĂȘtre allouĂ©e hiĂ©rarchiquement par PKI ou plutĂŽt de maniĂšre rĂ©partie par tirage au sort (comme le sont les clĂ©s SSH ou PGP aujourd'hui, ce qui serait prĂ©fĂ©rable, question vie privĂ©e). Ces identificateurs fondĂ©s sur la cryptographie permettent l'authentification rĂ©ciproque des machines (contrairement Ă  IP, oĂč il est trivial de mentir sur son adresse), et d'utiliser ensuite IPsec (RFC 7402) pour chiffrer la communication (HIP n'impose pas IPsec, plusieurs encapsulations des donnĂ©es sont possibles, et nĂ©gociĂ©es dynamiquement, mais, en pratique, la plupart des usages prĂ©vus reposent sur IPsec).

L'authentification permet d'ĂȘtre sĂ»r du HI de la machine avec qui on parle et, si le HI Ă©tait connu prĂ©alablement Ă  partir d'une source de confiance, d'ĂȘtre sĂ»r qu'on parle bien Ă  l'interlocuteur souhaitĂ©. (Si on ne connait pas le HI Ă  l'avance, on dit que HIP est en mode « opportuniste ».)

Cette sĂ©paration de l'identificateur et du localisateur est un sujet de recherche commun et d'autres propositions que HIP existent, comme LISP (RFC 6830) ou ILNP (RFC 6740). Dans tous les cas, les couches supĂ©rieures (comme TCP) ne verront que l'identificateur, permettant au localisateur de changer sans casser les sessions de transport en cours. (Un mĂ©canisme ressemblant est le Back to My Mac du RFC 6281.) L'annexe A.1 de notre RFC rappelle les avantages de cette approche. Et l'annexe A.2, lecture trĂšs recommandĂ©e, note Ă©galement ses dĂ©fauts, l'indirection supplĂ©mentaire ajoutĂ©e n'est pas gratuite, et entraine des nouveaux problĂšmes. Notamment, il faut crĂ©er un systĂšme de correspondance - mapping - entre les deux, systĂšme qui complexifie le projet. Il y a aussi la latence supplĂ©mentaire due au protocole d'Ă©change initial, qui est plus riche. Comparez cette honnĂȘtetĂ© avec les propositions plus ou moins pipeau de « refaire l'Internet en partant de zĂ©ro », qui ne listent jamais les limites et les problĂšmes de leurs solutions miracle.

Ce HI (Host Identifier) pourra ĂȘtre stockĂ© dans des annuaires publics, comme le DNS (RFC 8005), ou une DHT (RFC 6537), pour permettre le rendez-vous (RFC 8004) entre les machines.

Notez que ce n'est pas directement le Host Identifier, qui peut ĂȘtre trĂšs long, qui sera utilisĂ© dans les paquets IP, mais un condensat, le HIT (Host Identity Tag).

HIP intÚgre les leçons de l'expérience avec IP, notamment de l'importance d'authentifier la machine avec qui on parle. C'est ce qui est fait dans l'échange initial qui permet à un initiateur et un répondeur de se mettre à communiquer. Notamment, il y a obligation de résoudre un puzzle cryptographique, pour rendre plus difficile certaines attaques par déni de service. Voir à ce sujet « DOS-Resistant Authentication with Client Puzzles » de Tuomas Aura, Pekka Nikander et Jussipekka Leiwo, « Deamplification of DoS Attacks via Puzzles » de Jacob Beal et Tim Shepard ou encore « Examining the DOS Resistance of HIP » de Tritilanunt, Suratose, Boyd, Colin A., Foo, Ernest, et Nieto, Juan Gonzalez.

La sĂ©curitĂ© est un aspect important de HIP. Les points Ă  garder en tĂȘte sont :

  • Protection contre certaines attaques par dĂ©ni de service via le puzzle cryptographique Ă  rĂ©soudre.
  • Protection contre les attaques de l'homme du milieu si le HI a Ă©tĂ© obtenu par un mĂ©canisme sĂ»r. Cela ne marche Ă©videmment pas en mode opportuniste, oĂč l'initiateur ne connait pas le HI de son correspondant, et le dĂ©couvre une fois la connexion faite.
  • Le mode opportuniste peut ĂȘtre renforcĂ©, question sĂ©curitĂ©, par le TOFU (RFC 7435).
  • Tout mĂ©canisme de sĂ©paration de l'identificateur et du localisateur ouvre de nouveaux problĂšmes : que se passe-t-il si le correspondant ment sur son localisateur ? Est-ce que cela permet des attaques par rĂ©flexion ? C'est pour Ă©viter cela que les systĂšmes Ă  sĂ©paration de l'identificateur et du localisateur prĂ©voient, comme HIP, un test de l'existence d'une voie de retour (Cf. RFC 4225).
  • Enfin, on peut Ă©videmment mettre des ACL sur des HI mais leur structure « plate » fait qu'il n'y a pas d'agrĂ©gation possible de ces ACL (il faut une ACL par machine avec qui on correspond).
Au sujet du TOFU, le RFC cite «  Leap-of-faith security is enough for IP mobility » de Miika Kari Tapio Komu et Janne Lindqvist, « Security Analysis of Leap-of-Faith Protocols » de Viet Pham et Tuomas Aura et « Enterprise Network Packet Filtering for Mobile Cryptographic Identities » de Janne Lindqvist, Essi Vehmersalo, Miika Komu et Jukka Manner.

Notre RFC ne dĂ©crit qu'une architecture gĂ©nĂ©rale, il est complĂ©tĂ© par les RFC 7401, qui dĂ©crit le protocole, RFC 7402, RFC 8003, RFC 8004, RFC 8005, RFC 8046 et RFC 5207. Si des implĂ©mentations expĂ©rimentales existent dĂ©jĂ  et que des serveurs publics utilisent HIP, aucun dĂ©ploiement significatif n'a eu lieu (cf. l'article « Adoption barriers of network layer protocols: The case of host identity protocol de T. Leva, M. Komu, A. Keranen et S. Luukkainen). Comme le disait un des relecteurs du RFC, « There's a lot of valuable protocol design and deployment experience packed into this architecture and the associated protocol RFCs. At the same time, actual adoption and deployment of HIP so far appears to have been scarce. I don't find this surprising. The existing Internet network/transport/application protocol stack has already become sufficiently complicated that considerable expertise is required to manage it in all but the simplest of cases. Teams of skilled engineers routinely spend hours or days troubleshooting operational problems that crop up within or between the existing layers, and the collection of extensions, workarounds, identifiers, knobs, and failure cases continues to grow. Adding a major new layer--and a fairly complicated one at that--right in the middle of the existing stack seems likely to explode the already heavily-strained operational complexity budget of production deployments. ». L'annexe A.3 dĂ©crit les questions pratiques liĂ©es au dĂ©ploiement. Elle rappelle le compte-rendu d'expĂ©rience chez Boeing de Richard Paine dans son livre « Beyond HIP: The End to Hacking As We Know It ». Elle tord le cou Ă  certaines lĂ©gendes rĂ©pandues (que HIP ne fonctionne pas Ă  travers les routeurs NAT, ou bien qu'il faut le mettre en Ɠuvre uniquement dans le noyau.)

Ah, question implémentations (RFC 6538), on a au moins HIP for Linux et OpenHIP qui ont été adaptés aux derniÚres versions de HIP, et des protocoles associés.

Les changements depuis le RFC 4423 sont résumés en section 14. Il n'y en a pas beaucoup, à part l'intégration de l'expérience, acquise dans les treize derniÚres années (et résumée dans le RFC 6538) et des améliorations du texte. La nouvelle annexe A rassemble plein d'informations concrÚtes, notamment que les questions pratiques de déploiement de HIP, et sa lecture est trÚs recommandée à tous ceux et toutes celles qui s'intéressent à la conception de protocoles. La question de l'agilité cryptographique (RFC 7696) a également été détaillée.

Linux tmux – a multiplex tool for all Engineers

July 13th 2021 at 07:02

tmux provides multiple command windows in a single window to increase your productivity in Linux Operating System. tmux is a must tool to have for any Engineers. It has made my work and study more efficient. Please read through what tmux is from wikipedia and then install it to increase your work productivity.

What is tmux?

https://en.wikipedia.org/wiki/Tmux

Check the installation

Most of the linux systems do not come with tmux pre-installed so, you needs to install tmux.

[jdoe@centos8 ~]$ apt install tmux

Here is a quick tmux cheatsheet I have put together

* To exit from tmux session, press “Ctrl+b”, then enter “kill-session”, and hit [Enter] key.

To open a new pane, press “Ctrl+b”, followed by “%”.

To move to the default or original window on the left, press “Ctrl+b”, followed by “<–” left arrow key.

To move to the default or original window on the right, press “Ctrl+b”, followed by “–>” left arrow key.

Ctrl+b, then “

tmux make you work smarter not harder. Enjoy!

italchemy

❌