Add wireguard and start big refactor

This commit is contained in:
2024-10-31 15:20:10 +01:00
parent 769132af53
commit f5986a83f2
15 changed files with 7250 additions and 41 deletions

View File

@@ -1,15 +1,39 @@
mod namespace;
mod manage_interfaces;
mod wireguard_manager;
use std::io::Result;
use rtnetlink::NetworkNamespace;
use futures::executor::block_on;
use base64::prelude::*;
fn main() {
env_logger::Builder::from_default_env()
.format_timestamp_secs()
.filter(None, log::LevelFilter::Debug)
.init();
let priv_key_dirty = BASE64_STANDARD.decode(b"key1").unwrap();
let pub_key_dirty = BASE64_STANDARD.decode(b"key2").unwrap();
let mut priv_key: [u8; 32] = Default::default();
let mut pub_key: [u8; 32] = Default::default();
priv_key.copy_from_slice(&priv_key_dirty[0..32]);
pub_key.copy_from_slice(&pub_key_dirty[0..32]);
//namespace::create_ns::create_ns();
let ns_name = "test-newns".to_string();
block_on(NetworkNamespace::add(ns_name.clone()));
namespace::bind_interface::run_in_namespace(|| {namespace::bind_interface::set_lo_up().unwrap();},&ns_name);
block_on(NetworkNamespace::add(ns_name.clone())).unwrap();
namespace::bind_interface::run_in_namespace(|| {
manage_interfaces::set_interface_lo_up().unwrap();
},
&ns_name).unwrap();
namespace::bind_interface::run_in_namespace(|| {
manage_interfaces::create_wireguard_interface(String::from("wgiface"),
String::from("local_ip"),
String::from("remote_ip"),
24,
pub_key,
priv_key).unwrap();
},
&ns_name).unwrap();
//println!("{}",wireguard_manager::add_properties::set_params(pub_key, priv_key))
}

View File

@@ -0,0 +1,95 @@
use rtnetlink::{new_connection, Error, Handle};
use netlink_packet_route::link::LinkMessage;
use std::net::IpAddr;
use futures::TryStreamExt;
mod netlink;
pub fn create_wireguard_interface(
interface_name: String,
interface_ip: String,
peer_ip: String,
prefix: u8,
wg_pub_key: [u8; 32],
wg_priv_key: [u8;32]) -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
netlink::create_wireguard_interface(handle.clone(), interface_name.clone()).await?;
let link = netlink::get_link_interface(handle.clone(), interface_name.clone()).await?;
netlink::assign_ip(handle.clone(), link.clone(), interface_ip, prefix).await?;
crate::wireguard_manager::add_properties::set_params(wg_pub_key, wg_priv_key, peer_ip, interface_name.clone());
netlink::set_interface_up(handle, link).await?;
Ok(())
})
}
pub fn set_interface_lo_up() -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
let link = netlink::get_link_interface(handle.clone(), String::from("lo")).await?;
netlink::set_interface_up(handle, link).await?;
Ok(())
})
}
/*pub fn set_interface_up(interface: String) -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
let mut links = handle.link().get().match_name(interface).execute();
if let Some(link) = links.try_next().await.unwrap() {
let index = link.header.index;
log::debug!("index:{}", index);
handle
.link()
.set(index)
.up()
.execute()
.await.unwrap()
} else {
log::debug!("no link link lo found");
}
});
Ok(())
}
pub fn create_wireguard_interface(interface: String) -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
handle.link().add().wireguard(interface).execute().await.unwrap();
});
Ok(())
}
pub async fn assign_ip(handle: Handle, link: LinkMessage, interface: String, ip: String, prefix: u8) -> Result<(), Error> {
let usable_ip: IpAddr = match ip.parse() {
Ok(ip_ok) => ip_ok,
Err(_e) => {
log::debug!("malformed ip");
return Err(Error::InvalidIp(ip.into_bytes()));
},
};
handle
.address()
.add(link.header.index, usable_ip, prefix)
.execute()
.await
}*/
pub fn get_inferfaces() -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
log::debug!("ARE WE STOPPING YET???");
let mut links = handle.link().get().match_name("lo".to_string()).execute();
if let Some(link) = links.try_next().await.unwrap() {
let index = link.header.index;
log::debug!("index:{}", index);
} else {
println!("no link link lo found");
}
});
Ok(())
}

View File

@@ -0,0 +1,53 @@
use rtnetlink::{new_connection, Error, Handle};
use netlink_packet_route::link::LinkMessage;
use std::net::IpAddr;
use futures::TryStreamExt;
pub async fn set_interface_up(handle: Handle,
link: LinkMessage) -> Result<(), Error> {
let index = link.header.index;
log::debug!("index: {}", index);
handle
.link()
.set(index)
.up()
.execute()
.await
}
pub async fn create_wireguard_interface(
handle: Handle,
interface: String) -> Result<(), Error> {
handle.link().add().wireguard(interface).execute().await
}
pub async fn assign_ip(
handle: Handle,
link: LinkMessage,
ip: String,
prefix: u8) -> Result<(), Error> {
let usable_ip: IpAddr = match ip.parse() {
Ok(ip_ok) => ip_ok,
Err(_e) => {
log::debug!("malformed ip");
return Err(Error::InvalidIp(ip.into_bytes()));
},
};
handle
.address()
.add(link.header.index, usable_ip, prefix)
.execute()
.await
}
pub async fn get_link_interface(
handle: Handle,
interface: String) -> Result<LinkMessage ,Error> {
let mut links = handle.link().get().match_name(interface).execute();
if let Some(link) = links.try_next().await.unwrap() {
Ok(link)
} else {
log::debug!("no link link lo found");
Err(Error::RequestFailed)
}
}

View File

@@ -101,7 +101,7 @@ fn prepare_namespace(ns_name: &String) -> Result<(), ()> {
let mut mount_flags = MsFlags::empty();
mount_flags.insert(MsFlags::MS_REC);
mount_flags.insert(MsFlags::MS_PRIVATE);
if let Err(e) = mount::<PathBuf, PathBuf, str, PathBuf>(None, &PathBuf::from("/"), None, mount_flags, None) {
if let Err(_e) = mount::<PathBuf, PathBuf, str, PathBuf>(None, &PathBuf::from("/"), None, mount_flags, None) {
log::error!("Can not remount root directory");
()
}
@@ -137,41 +137,3 @@ fn prepare_namespace(ns_name: &String) -> Result<(), ()> {
Ok(())
}
pub fn set_lo_up() -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
log::debug!("ARE WE STOPPING YET???");
let mut links = handle.link().get().match_name("lo".to_string()).execute();
if let Some(link) = links.try_next().await.unwrap() {
let index = link.header.index;
log::debug!("index:{}", index);
handle
.link()
.set(index)
.up()
.execute()
.await.unwrap()
} else {
println!("no link link lo found");
}
});
Ok(())
}
pub fn get_inferfaces() -> Result<(), Error> {
tokio::runtime::Runtime::new().unwrap().handle().block_on( async {
let (connection, handle, _) = new_connection().unwrap();
tokio::spawn(connection);
log::debug!("ARE WE STOPPING YET???");
let mut links = handle.link().get().match_name("lo".to_string()).execute();
if let Some(link) = links.try_next().await.unwrap() {
let index = link.header.index;
log::debug!("index:{}", index);
} else {
println!("no link link lo found");
}
});
Ok(())
}

View File

@@ -0,0 +1,46 @@
use crate::wireguard_manager::wireguard_wrapper;
use std::ffi::CString;
pub fn get_names() -> i32 {
let index: i32;
/*unsafe {
let names = wireguard::wg_list_device_names();
index = *names
}
return index;*/
unsafe {
index = wireguard_wrapper::it_works();
}
index
}
pub fn set_params(mut wg_pub_key: [u8; 32],
mut wg_priv_key: [u8;32],
peer_ip: String,
interface_name: String) -> bool {
let mut ret = false;
unsafe {
let mut peer = wireguard_wrapper::generate_new_peer(&mut wg_pub_key,
CString::new(peer_ip).unwrap().into_raw(),
51820);
println!("crea la semilla");
let mut device = wireguard_wrapper::generate_new_device(&mut wg_priv_key,
CString::new(interface_name).unwrap().into_raw(),
51820, peer);
println!("crea la interfaz de red");
//let status_add_device = wireguard_wrapper::wg_add_device(device.name.as_ptr());
let status_set_device = wireguard_wrapper::wg_set_device(&mut device);
//println!("dispositivo: {}", CString::from_raw(device.name.as_mut_ptr()).to_str().unwrap());
/*if ret {
println!("añade el dispositivo");
//println!("dispositivo: {}", CString::from_raw(device.name.as_mut_ptr()).to_str().unwrap());
ret = ret && (wireguard_wrapper::wg_set_device(&mut device) < 0);
}*/
//ret = status_add_device >= 0 && status_set_device >= 0;
ret = status_set_device >= 0;
wireguard_wrapper::clean_device(&mut peer);
}
ret
}

View File

@@ -0,0 +1,2 @@
mod wireguard_wrapper;
pub mod add_properties;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,105 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#ifndef WIREGUARD_H
#define WIREGUARD_H
#include <net/if.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <time.h>
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t wg_key[32];
typedef char wg_key_b64_string[((sizeof(wg_key) + 2) / 3) * 4 + 1];
/* Cross platform __kernel_timespec */
struct timespec64 {
int64_t tv_sec;
int64_t tv_nsec;
};
typedef struct wg_allowedip {
uint16_t family;
union {
struct in_addr ip4;
struct in6_addr ip6;
};
uint8_t cidr;
struct wg_allowedip *next_allowedip;
} wg_allowedip;
enum wg_peer_flags {
WGPEER_REMOVE_ME = 1U << 0,
WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
WGPEER_HAS_PRESHARED_KEY = 1U << 3,
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4
};
typedef union wg_endpoint {
struct sockaddr addr;
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
} wg_endpoint;
typedef struct wg_peer {
enum wg_peer_flags flags;
wg_key public_key;
wg_key preshared_key;
wg_endpoint endpoint;
struct timespec64 last_handshake_time;
uint64_t rx_bytes, tx_bytes;
uint16_t persistent_keepalive_interval;
struct wg_allowedip *first_allowedip, *last_allowedip;
struct wg_peer *next_peer;
} wg_peer;
enum wg_device_flags {
WGDEVICE_REPLACE_PEERS = 1U << 0,
WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
WGDEVICE_HAS_LISTEN_PORT = 1U << 3,
WGDEVICE_HAS_FWMARK = 1U << 4
};
typedef struct wg_device {
char name[IFNAMSIZ];
uint32_t ifindex;
enum wg_device_flags flags;
wg_key public_key;
wg_key private_key;
uint32_t fwmark;
uint16_t listen_port;
struct wg_peer *first_peer, *last_peer;
} wg_device;
#define wg_for_each_device_name(__names, __name, __len) for ((__name) = (__names), (__len) = 0; ((__len) = strlen(__name)); (__name) += (__len) + 1)
#define wg_for_each_peer(__dev, __peer) for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
#define wg_for_each_allowedip(__peer, __allowedip) for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); (__allowedip) = (__allowedip)->next_allowedip)
int wg_set_device(wg_device *dev);
int wg_get_device(wg_device **dev, const char *device_name);
int wg_add_device(const char *device_name);
int wg_del_device(const char *device_name);
void wg_free_device(wg_device *dev);
char *wg_list_device_names(void); /* first\0second\0third\0forth\0last\0\0 */
void wg_key_to_base64(wg_key_b64_string base64, const wg_key key);
int wg_key_from_base64(wg_key key, const wg_key_b64_string base64);
bool wg_key_is_zero(const wg_key key);
void wg_generate_public_key(wg_key public_key, const wg_key private_key);
void wg_generate_private_key(wg_key private_key);
void wg_generate_preshared_key(wg_key preshared_key);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
#include "wireguard_wrapper.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
void generate_default_ipv4(wg_allowedip *ip);
void generate_default_ipv6(wg_allowedip *ip);
wg_endpoint generate_endponit(char *ip, unsigned short port);
wg_peer generate_new_peer(wg_key *pub_key, char *ip, unsigned short port) {
wg_allowedip *ipv4, *ipv6;
ipv4 = malloc (sizeof (wg_allowedip));
ipv6 = malloc (sizeof (wg_allowedip));
generate_default_ipv4(ipv4);
generate_default_ipv6(ipv6);
ipv4->next_allowedip = ipv6;
wg_peer new_peer = {
.flags = WGPEER_HAS_PUBLIC_KEY | WGPEER_REPLACE_ALLOWEDIPS,
//.public_key = pub_key,
.first_allowedip = ipv4,
.last_allowedip = ipv6,
.endpoint = generate_endponit (ip, port),
};
strcpy(new_peer.public_key, pub_key);
return new_peer;
}
wg_device generate_new_device(wg_key *priv_key,
char device_name[IFNAMSIZ],
unsigned short port,
wg_peer peer)
{
wg_device new_device = {
//.private_key = priv_key,
.listen_port = port,
.flags = WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_LISTEN_PORT,
.first_peer = &peer,
.last_peer = &peer,
};
strcpy(new_device.name, device_name);
strcpy(new_device.private_key, priv_key);
printf("str2: %s\n",new_device.name);
wg_key_b64_string key, key2;
wg_key_to_base64(key, new_device.first_peer->public_key);
printf("str2: %s\n",key);
wg_key_to_base64(key2, new_device.private_key);
printf("str3: %s\n",key2);
return new_device;
}
wg_endpoint generate_endponit(char *ip, unsigned short port) {
struct in_addr ipv4;
inet_pton (AF_INET, ip, &ipv4);
struct sockaddr_in address ={
.sin_family = AF_INET,
.sin_port = port,
.sin_addr = ipv4,
};
wg_endpoint ret = {
.addr4 = address,
};
return ret;
}
void generate_default_ipv4(wg_allowedip *ip) {
struct in_addr ipv4;
inet_pton (AF_INET, "0.0.0.0", &ipv4);
*ip = (struct wg_allowedip) {
.family = AF_INET,
.ip4 = ipv4,
};
}
void generate_default_ipv6(wg_allowedip *ip) {
struct in6_addr ipv6;
inet_pton (AF_INET6, "::0", &ipv6);
*ip = (struct wg_allowedip) {
.family = AF_INET6,
.ip6 = ipv6,
};
}
void clean_device(wg_peer *peer) {
free(peer->first_allowedip);
free(peer->last_allowedip);
}
void list_devices(void)
{
char *device_names, *device_name;
size_t len;
device_names = wg_list_device_names();
if (!device_names) {
perror("Unable to get device names");
exit(1);
}
wg_for_each_device_name(device_names, device_name, len) {
wg_device *device;
wg_peer *peer;
wg_key_b64_string key;
if (wg_get_device(&device, device_name) < 0) {
perror("Unable to get device");
continue;
}
if (device->flags & WGDEVICE_HAS_PUBLIC_KEY) {
wg_key_to_base64(key, device->public_key);
printf("%s has public key %s\n", device_name, key);
} else
printf("%s has no public key\n", device_name);
wg_for_each_peer(device, peer) {
wg_key_to_base64(key, peer->public_key);
printf(" - peer %s\n", key);
}
wg_free_device(device);
}
free(device_names);
}
int it_works() {
list_devices();
return 5;
}

View File

@@ -0,0 +1,10 @@
#include "wireguard.h"
wg_peer generate_new_peer(wg_key *pub_key,
char *ip,
unsigned short port);
wg_device generate_new_device(wg_key *priv_key,
char device_name[IFNAMSIZ],
unsigned short port,
wg_peer peer);
int it_works();
void clean_device(wg_peer *peer);

File diff suppressed because it is too large Load Diff