#include <iostream>
#include <sys/wait.h>
#include <sys/mount.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <string.h>
#include <net/route.h>
#define STACK_SIZE (1024 * 1024)
using namespace std;
static char stack[STACK_SIZE];
int setip(char *name,char *addr,char *netmask) {
struct ifreq ifr;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ifr.ifr_addr.sa_family = AF_INET;
inet_pton(AF_INET, addr, ifr.ifr_addr.sa_data + 2);
ioctl(fd, SIOCSIFADDR, &ifr);
inet_pton(AF_INET, netmask, ifr.ifr_addr.sa_data + 2);
ioctl(fd, SIOCSIFNETMASK, &ifr);
//get flags
ioctl(fd, SIOCGIFFLAGS, &ifr);
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
// set flags
//ioctl(fd, SIOCSIFFLAGS, &ifr);
if(ioctl(fd, SIOCSIFFLAGS, &ifr) < 0 )
perror("ioctl");
return 0;
}
int setRoute(char *name, char *addr) {
int sockfd;
struct rtentry rt;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("socket creation failed\n");
return 0;
}
struct sockaddr_in *sockinfo = (struct sockaddr_in *)&rt.rt_gateway;
sockinfo->sin_family = AF_INET;
sockinfo->sin_addr.s_addr = inet_addr(addr);
sockinfo = (struct sockaddr_in *)&rt.rt_dst;
sockinfo->sin_family = AF_INET;
sockinfo->sin_addr.s_addr = INADDR_ANY;
sockinfo = (struct sockaddr_in *)&rt.rt_genmask;
sockinfo->sin_family = AF_INET;
sockinfo->sin_addr.s_addr = INADDR_ANY;
rt.rt_flags = RTF_UP | RTF_GATEWAY;
rt.rt_dev = name;
if(ioctl(sockfd, SIOCADDRT, &rt) < 0 ){
perror("ioctl");
}
return 0;
}
void setInterfaceUp(char *name){
int sockfd;
struct ifreq ifr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
return;
memset(&ifr, 0, sizeof ifr);
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ifr.ifr_flags |= IFF_UP;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0 ){
perror("ioctl");
}
}
int child(void* arg)
{
sleep(1);
if (mount("none", "/", NULL, MS_PRIVATE|MS_REC, NULL) == -1) {
perror("mount");
exit(1);
}
if (chroot("/path/to/new/root/") == -1){
perror("chroot");
exit(1);
}
if (chdir("/") == -1){
perror("chdir");
exit(1);
}
if (mount("proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL) == -1) {
perror("mount");
exit(1);
}
setip("veth1","192.168.0.1","255.255.255.0");
setRoute("veth1", "192.168.0.2");
setInterfaceUp("lo");
if (setresuid(1001, 1001, 1001) == -1){
perror("setresuid");
exit(1);
}
if (execlp("/bin/bash", "/bin/bash", NULL) == -1){
perror("execlp");
exit(1);
}
return 1;
}
int main()
{
if(setresuid(0, 0, 0) == -1 ){
perror("setresuid");
exit(1);
}
char buf[255];
pid_t pid = clone(child, stack+STACK_SIZE,
CLONE_NEWNET|CLONE_NEWNS|CLONE_NEWCGROUP|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWPID|SIGCHLD, NULL);
if (pid == -1){
perror("clone");
exit(1);
}
sprintf(buf,"ip link add name veth0 type veth peer name veth1 netns %d",pid);
if (system(buf) == -1){
perror("system");
exit(1);
}
setip("veth0","192.168.0.2","255.255.255.0");
if (setresuid(1001, 1001, 1001) == -1){
perror("setresuid");
exit(1);
}
if (waitpid(pid, NULL, 0) == -1){
perror("waitpid");
exit(1);
}
return 0;
}
Źródło: