QEMU сеть
Материал из test
Две машины, связанные сетью
Связанные между собой, изолированные от хоста.
На хосте нужно создать два tap-интерфейса и бридж:
sudo ip tuntap add dev tap0 mode tap sudo ip tuntap add dev tap1 mode tap sudo ip link set tap0 up sudo ip link set tap1 up sudo ip link add name br0 type bridge sudo ip link set tap0 master br0 sudo ip link set tap1 master br0 sudo ip link set dev br0 up
Параметры запуска QEMU для сети:
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000,netdev=net0,mac=52:55:00:d1:55:01
Запуск может выглядеть например так (для разных машин нужно выбрать разный mac-адрес):
qemu-system-x86_64 -m 2048 -smp 2 -drive file=my_disk.qcow2,format=qcow2 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000,netdev=net0,mac=52:55:00:d1:55:01
В самих машинах нужно настроить статический ip-адрес.
В /etc/network/interfaces прописать, например:
iface ens3 inet static
address 192.168.0.1
netmask 255.255.255.0
Виртуалка в подсети хоста, получает адрес от роутера
sudo ip link add name br0 type bridge sudo ip link set br0 up sudo ip link set enp59s0 master br0 sudo ip link set enp59s0 up sudo dhcpcd br0 sudo ip tuntap add tap0 mode tap sudo ip link set tap0 master br0 sudo ip link set tap0 up sudo ip r del default via 192.168.1.1 dev enp59s0 sudo ip r del 192.168.1.0/24 dev enp59s0 proto kernel scope link src 192.168.1.13 metric 100
Запуск qemu:
qemu-system-x86_64 -m 2048 -smp 4 -drive file=test.qcow2,format=qcow2 -accel kvm -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000,netdev=net0,mac=52:54:00:11:22:33
Вернуть обратно:
sudo ip link set tap0 nomaster sudo ip link delete tap0 sudo ip link set enp59s0 nomaster sudo ip link set br0 down sudo ip link delete br0 sudo dhcpcd enp59s0
Tun интерфейс
sudo ip tuntap add dev tun0 mode tun sudo ip link set tun0 up sudo ip addr add 10.0.0.1/24 dev tun0
Читает пакеты из tun-интерфейса
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <errno.h>
void print_hex(const unsigned char *buf, size_t len) {
for(size_t i = 0; i < len; i++) {
printf("%02x ", buf[i]);
}
printf("\n");
}
int main(void) {
printf("hi\n");
int tun_fd;
const char *iface_name = "tun0";
struct ifreq ifr;
int ret = 0;
tun_fd = open("/dev/net/tun", O_RDWR);
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, iface_name, IFNAMSIZ - 1);
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
ret = ioctl(tun_fd, TUNSETIFF, (void*)&ifr);
unsigned char buffer[2048];
ssize_t bytes_read;
while(1) {
bytes_read = read(tun_fd, buffer, sizeof(buffer));
printf("read %zd bytes\n", bytes_read);
print_hex(buffer, bytes_read);
}
close(tun_fd);
return 0;
}