diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c38d68d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "roles/ansible-gobgp"] + path = roles/ansible-gobgp + url = https://git.dotya.ml/mirre-bt/ansible-gobgp +[submodule "roles/ansible-fprobe"] + path = roles/ansible-fprobe + url = https://git.dotya.ml/mirre-bt/ansible-fprobe diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b64f00e --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +ap = ansible-playbook +ausr = ansible +privk = ~/.ssh/tf-ansible +pbdir = playbooks +pbname = lab.yml + +.PHONY: ans infra destroy + +ans: + $(ap) -u $(ausr) --private-key $(privk) -i hosts $(pbdir)/$(pbname) + +infra: + cd vms; make infra + +destroy: + cd vms; make destroy diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..a7584d8 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,13 @@ +[defaults] +inventory = hosts +remote_tmp = $HOME/.ansible/tmp +remote_user = root +nocows = 1 +roles_path = roles +retry_files_enabled = False +max_diff_size = 250000 + +[ssh_connection] +pipelining = True +scp_if_ssh = True +retries = 7 diff --git a/playbooks/host_vars/r_edge.yml b/playbooks/host_vars/r_edge.yml new file mode 100644 index 0000000..4c37bd6 --- /dev/null +++ b/playbooks/host_vars/r_edge.yml @@ -0,0 +1,20 @@ +GOBGP_CONF: + global: + config: + as: 65000 + router-id: 10.16.7.1 + port: 179 + neighbors: + - config: + neighbor-address: 10.16.7.2 + peer-as: 65001 + transport: + config: + remote-port: "179" + add-paths: + config: + send-max: "8" + receive: false + afi-safis: + - config: + afi-safi-name: ipv4-unicast diff --git a/playbooks/host_vars/r_upstream.yml b/playbooks/host_vars/r_upstream.yml new file mode 100644 index 0000000..c5e7cf6 --- /dev/null +++ b/playbooks/host_vars/r_upstream.yml @@ -0,0 +1,20 @@ +GOBGP_CONF: + global: + config: + as: 65001 + router-id: 10.16.7.2 + port: 179 + neighbors: + - config: + neighbor-address: 10.16.7.1 + peer-as: 65000 + transport: + config: + remote-port: "179" + add-paths: + config: + send-max: "8" + receive: true + afi-safis: + - config: + afi-safi-name: ipv4-unicast diff --git a/playbooks/lab.yml b/playbooks/lab.yml new file mode 100644 index 0000000..6e0112e --- /dev/null +++ b/playbooks/lab.yml @@ -0,0 +1,28 @@ +--- +- hosts: defender + user: ansible + become: true + become_user: root + become_method: sudo + roles: + - { role: waitpls } + - { role: ndpi } + - { role: fastnetmon } + +- group: router + user: ansible + become: true + become_user: root + become_method: sudo + roles: + - { role: waitpls } + - { role: ansible-gobgp } + +- hosts: edge + user: ansible + become: true + become_user: root + become_method: sudo + roles: + - { role: waitpls } + - { role: ansible-fprobe } diff --git a/roles/ansible-fprobe b/roles/ansible-fprobe new file mode 160000 index 0000000..c3d75c8 --- /dev/null +++ b/roles/ansible-fprobe @@ -0,0 +1 @@ +Subproject commit c3d75c837813735a708625949b387b1216ae215d diff --git a/roles/ansible-gobgp b/roles/ansible-gobgp new file mode 160000 index 0000000..d39074a --- /dev/null +++ b/roles/ansible-gobgp @@ -0,0 +1 @@ +Subproject commit d39074a8e65f1d2b5bce155b257ab85abcfde302 diff --git a/vms/cloudinit.host-defender.cfg b/vms/cloudinit.host-defender.cfg index dc3d175..713eebc 100644 --- a/vms/cloudinit.host-defender.cfg +++ b/vms/cloudinit.host-defender.cfg @@ -1,17 +1,26 @@ #cloud-config # vim: ft=yaml -runcmd: +bootcmd: - cat /etc/resolv.conf - uname -r - timedatectl set-ntp 1 - timedatectl set-timezone Europe/Bratislava - systemctl disable --now dnf-makecache.timer + - systemctl stop systemd-resolved + - echo "nameserver 8.8.8.8" > /etc/resolv.conf + - dnf config-manager --set-disabled fedora-cisco-openh264 - dnf config-manager --set-enabled updates updates-testing + - sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab + - sleep 10 + +runcmd: + - cat /etc/resolv.conf + - uname -r - dnf upgrade --refresh -y - dnf distro-sync -y - - dnf clean all - - sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab + - ldconfig + - touch /.plsgo write_files: - content: | @@ -25,6 +34,12 @@ write_files: owner: root:root permissions: '0644' + - content: | + /usr/local/lib + path: /etc/ld.so.conf.d/local.conf + owner: root:root + permissions: '0644' + ssh_pwauth: true chpasswd: list: | @@ -38,6 +53,8 @@ users: - name: ansible ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtG6NCgdLHX4ztpfvYNRaslKWZcl6KdTc1DehVH4kAL + # the tf-ansible key + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ9JEzfMs+O6I5JYRQ+gHWClvCqaNTdop8ncDeSj+RWs sudo: ['ALL=(ALL) NOPASSWD:ALL'] shell: /bin/bash groups: wheel @@ -58,7 +75,7 @@ power_state: delay: "+1" mode: reboot condition: true - timeout: 120 # seconds + timeout: 300 # seconds packages: - vim @@ -78,6 +95,54 @@ packages: - tcpdump - tcpflow - tcptrack + # fastnetmon/nDPI build requirements + - git + - make + - cmake + - automake + - gcc + - gcc-c++ + - libgcc + - libstdc++-devel + - libstdc++-static + - glibc-devel + - binutils + - flex + - bison + - openmpi-devel + - which + - file + - grpc-cli + - grpc-cpp + - grpc-devel + - grpc-plugins + - protobuf-c-devel + - protobuf-c-compiler + - protobuf-compiler + - cppunit + - log4cpp-devel + - json-c-devel + - capnproto-devel + - capnproto-libs + - libpcap-devel + - hiredis-devel + - mongo-c-driver-devel + - mongo-c-driver-libs + - boost-devel + - boost-atomic + - boost-chrono + - boost-date-time + - boost-system + - boost-program-options + - boost-regex + - boost-thread + - libtool + - autoconf + - pkgconf + - ncurses-c++-libs + - ncurses-devel + - ncurses-libs + - ncurses-static package_upgrade: false package_reboot_if_required: true diff --git a/vms/cloudinit.router.cfg b/vms/cloudinit.router.cfg index abecf90..8707c10 100644 --- a/vms/cloudinit.router.cfg +++ b/vms/cloudinit.router.cfg @@ -8,6 +8,8 @@ runcmd: - timedatectl set-timezone Europe/Bratislava - dnf config-manager --set-enabled updates updates-testing - sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab + - sleep 10 + - touch /.plsgo write_files: - content: | @@ -20,6 +22,12 @@ write_files: path: /etc/dnf/dnf.conf owner: root:root permissions: '0644' + - content: | + net.ipv4.ip_forward = 1 + path: /etc/sysctl.conf + owner: root:root + permissions: '0644' + append: true ssh_pwauth: true chpasswd: @@ -34,6 +42,8 @@ users: - name: ansible ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtG6NCgdLHX4ztpfvYNRaslKWZcl6KdTc1DehVH4kAL + # the tf-ansible key + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ9JEzfMs+O6I5JYRQ+gHWClvCqaNTdop8ncDeSj+RWs sudo: ['ALL=(ALL) NOPASSWD:ALL'] shell: /bin/bash groups: wheel @@ -54,6 +64,7 @@ power_state: delay: "+1" mode: reboot condition: true + timeout: 300 packages: - vim diff --git a/vms/main.tf b/vms/main.tf index a88a56d..f1cc5df 100644 --- a/vms/main.tf +++ b/vms/main.tf @@ -52,6 +52,19 @@ variable "category" { type = string default = "host" } +variable "subnets" { + type = list(string) +} +variable "network_names" { + type = list(string) +} +variable "dhcp" { + type = list(bool) +} +variable "ssh_private_key" { + description = "the key to use for ansible stuff" + default = "~/.ssh/tf-ansible" +} # base OS image resource "libvirt_volume" "baseosimage" { @@ -94,6 +107,17 @@ resource "libvirt_cloudinit_disk" "commoninit" { user_data = data.template_file.user_data[each.key].rendered } +resource "libvirt_network" "additional_networks" { + count = length(var.subnets) + name = var.network_names[count.index] + bridge = "br_${var.network_names[count.index]}" + mode = "route" + addresses = ["${var.subnets[count.index]}"] + dhcp { + enabled = var.dhcp[count.index] + } +} + # net-lab domains loop resource "libvirt_domain" "net-lab" { for_each = var.hosts @@ -110,6 +134,16 @@ resource "libvirt_domain" "net-lab" { # do not wait for a lease if networkname == "host-bridge" wait_for_lease = var.networkname == "host-bridge" ? false : true } + dynamic "network_interface" { + for_each = each.value.network + content { + network_name = network_interface.value["name"] + mac = network_interface.value["mac"] + addresses = network_interface.value["address"] + wait_for_lease = network_interface.value.mode == "bridge" ? false : true + } + } + disk { volume_id = element(libvirt_volume.qcow2_volume[each.key].*.id, 1) @@ -117,6 +151,25 @@ resource "libvirt_domain" "net-lab" { cloudinit = libvirt_cloudinit_disk.commoninit[each.value.name].id + provisioner "local-exec" { + command = < hosts + echo h_defender >> hosts + echo "[defender:vars]" >> hosts + echo "[router]" >> hosts + echo r_upstream >> hosts + echo r_edge >> hosts + echo "[router:vars]" >> hosts + echo "[attacker]" >> hosts + echo h_attacker >> hosts + echo "[attacker:vars]" >> hosts + echo "[victim]" >> hosts + echo h_victim >> hosts + echo "[victim:vars]" >> hosts + ansible-playbook -u ansible --private-key ${var.ssh_private_key} -i hosts playbooks/lab.yml + EOF + } + } diff --git a/vms/terraform.tfvars b/vms/terraform.tfvars index 3984560..5afbbf9 100644 --- a/vms/terraform.tfvars +++ b/vms/terraform.tfvars @@ -14,6 +14,9 @@ baseimagediskpool = "default" domainname = "local" networkname = "default" # default==NAT +subnets = ["10.16.4.0/24", "10.16.5.0/24", "10.16.6.0/24", "10.16.7.0/30"] +network_names = ["inner", "outer", "dmz", "router"] +dhcp = [true, false, false, false] # host-specific settings # RAM in bytes @@ -28,46 +31,102 @@ hosts = { mac = "00:00:00:13:37:22", sourceimage = "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2", category = "host-victim", + network = { + "inner" = { + name = "inner", + mode = "dhcp", + address = ["10.16.4.7"], + mac = "00:04:00:13:37:22", + }, + } }, "h_attacker" = { - name = "h_attacker", - vcpu = 1, - memory = "1024", - diskpool = "default", - disksize = "9370000000", - mac = "00:00:00:13:37:23", - sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", + name = "h_attacker", + vcpu = 1, + memory = "1024", + diskpool = "default", + disksize = "9370000000", + mac = "00:00:00:13:37:23", + # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", + sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", category = "host-attacker", + network = { + "outer" = { + name = "outer", + mode = "route", + address = ["10.16.5.1"], + mac = "00:05:00:13:37:23", + }, + } }, "r_edge" = { - name = "r_edge", - vcpu = 1, - memory = "768", - diskpool = "default", - disksize = "4300000000", - mac = "00:00:00:13:37:24", - sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", + name = "r_edge", + vcpu = 1, + memory = "768", + diskpool = "default", + disksize = "4300000000", + mac = "00:00:00:13:37:24", + # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", + sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", category = "router", + network = { + "dmz" = { + name = "dmz", + mode = "route", + address = ["10.16.6.1"], + mac = "00:06:00:13:37:24", + }, + "router" = { + name = "router", + mode = "route", + address = ["10.16.7.1"], + mac = "00:07:00:13:37:24", + }, + } }, "r_upstream" = { - name = "r_upstream", - vcpu = 1, - memory = "768", - diskpool = "default", - disksize = "4300000000", - mac = "00:00:00:13:37:25", - sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", + name = "r_upstream", + vcpu = 1, + memory = "768", + diskpool = "default", + disksize = "4300000000", + mac = "00:00:00:13:37:25", + # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", + sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", category = "router", + network = { + "outer" = { + name = "outer", + mode = "route", + address = ["10.16.5.1"], + mac = "00:05:00:13:37:25", + }, + "router" = { + name = "router", + mode = "route", + address = ["10.16.7.2"], + mac = "00:07:00:13:37:25", + }, + }, }, "h_defender" = { - name = "h_defender", - vcpu = 1, - memory = "1024", - diskpool = "default", - disksize = "9370000000", - mac = "00:00:00:13:37:26", - sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", + name = "h_defender", + vcpu = 1, + memory = "2048", + diskpool = "default", + disksize = "9370000000", + mac = "00:00:00:13:37:26", + # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", + sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", category = "host-defender", + network = { + "dmz" = { + name = "dmz", + mode = "route", + address = ["10.16.6.4"], + mac = "00:06:00:13:37:26", + }, + }, }, }