Commit 6636c1ee authored by 神楽坂玲奈's avatar 神楽坂玲奈

new

parent e073c3d2
Pipeline #16662 failed with stages
in 17 seconds
......@@ -3,7 +3,7 @@ project(tun)
set(CMAKE_CXX_STANDARD 23)
add_executable(tun src/main.cpp src/Config.cpp src/checksum.cpp)
add_executable(tun src/main.cpp src/Router.h)
set(CMAKE_CXX_FLAGS_DEBUG -ggdb)
......@@ -12,3 +12,8 @@ target_link_libraries(tun Threads::Threads)
find_package(nlohmann_json REQUIRED)
target_link_libraries(tun nlohmann_json::nlohmann_json)
find_package(Boost REQUIRED)
target_link_libraries(tun Boost)
target_link_libraries(tun b64)
\ No newline at end of file
#ifndef TUN_CONFIG_H
#define TUN_CONFIG_H
#include <nlohmann/json.hpp>
#include <boost/core/noncopyable.hpp>
using json = nlohmann::json;
......@@ -35,3 +39,5 @@ void from_json(const json& j, Config& p) {
j.at("local_secret").get_to(p.local_secret);
j.at("routers").get_to(p.routers);
}
#endif //TUN_CONFIG_H
\ No newline at end of file
#ifndef TUN_ROUTER_H
#define TUN_ROUTER_H
#include "Config.h"
#include <boost/core/noncopyable.hpp>
#include <b64/decode.h>
#include <netdb.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <fcntl.h>
#include <sys/ioctl.h>
class Router : private boost::noncopyable {
public:
static const int secret_length = 32;
static std::map<std::pair<unsigned char, unsigned char>, int> raws; // (family,proto) => fd
static std::map<int, Router *> tuns; // fd => router
static std::map<int, Router *> all; // id => router
static unsigned char local_secret[secret_length];
const ConfigRouter &config;
unsigned char secret[secret_length];
sockaddr_storage remote_addr{};
int tun;
int raw;
explicit Router(const ConfigRouter &config) : config(config) {
create_secret(config.remote_secret, secret);
create_remote_addr();
create_tun();
create_raw();
system(config.up.c_str());
all[config.remote_id] = this;
tuns[tun] = this;
};
static void create_secret(const std::string &secret, unsigned char *target) {
base64::decoder decoder;
decoder.decode(secret.c_str(), secret.length(), (char *) target);
}
void create_remote_addr() {
if (config.endpoint.empty()) {
addrinfo hints = {.ai_family = config.family};
addrinfo *result;
if (auto ret = getaddrinfo(config.endpoint.c_str(), nullptr, &hints, &result) != 0) {
puts(gai_strerror(ret));
throw;
}
remote_addr = *(sockaddr_storage *) result->ai_addr;
freeaddrinfo(result);
}
}
void create_tun() {
ifreq ifr{};
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, config.dev.c_str(), IFNAMSIZ);
tun = open("/dev/net/tun", O_RDWR);
if (tun < 0) {
perror("tun init error");
throw;
}
if (ioctl(tun, TUNSETIFF, &ifr) < 0) {
perror("ioctl error");
throw;
}
}
void create_raw() {
auto key = std::make_pair(config.family, config.proto);
if (!raws.contains(key)) {
if (auto result = socket(config.family, SOCK_RAW, config.proto) < 0) {
perror("socket init error");
throw;
} else {
raws[key] = result;
}
}
raw = raws[key];
}
void encrypt(unsigned char *data, size_t length) {
for (size_t i = 0; i < length; i++) {
data[i] ^= local_secret[i % secret_length];
}
}
void decrypt(unsigned char *data, size_t length) {
for (size_t i = 0; i < length; i++) {
data[i] ^= secret[i % secret_length];
}
}
};
#endif
#include <iostream>
#include <thread>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/ip.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <cstring>
#include <nlohmann/json.hpp>
#include <linux/ipv6.h>
#include <vector>
#include <linux/ip.h>
#include "checksum.h"
#include "Config.h"
#include "Router.h"
using json = nlohmann::json;
struct Meta {
unsigned char src_id;
unsigned char dst_id;
unsigned short reversed;
unsigned short reserved;
};
unsigned char local_id;
unsigned char remote_id;
sockaddr_storage remote_addr{};
class Secret {
private:
char *key;
size_t length;
public:
Secret(char *key) : key(key), length(strlen(key)) {}
void encrypt(unsigned char *data, size_t length) {
for (size_t i = 0; i < length; i++) {
data[i] ^= key[i % this->length];
}
}
void decrypt(unsigned char *data, size_t length) {
encrypt(data, length);
}
};
Secret *localSecret;
Secret *remoteSecret;
#include <linux/ipv6.h>
#include <vector>
Config config;
// internet -> tun
void inbound(int raw, int tun) {
void inbound(int raw) {
unsigned char buffer[ETH_DATA_LEN];
sockaddr_storage address;
socklen_t address_length = sizeof(address);
......@@ -58,10 +34,11 @@ void inbound(int raw, int tun) {
auto overhead = packet->ihl * 4;
auto payload = buffer + overhead;
auto meta = (Meta *) payload;
if (!(meta->src_id == remote_id && meta->dst_id == local_id && meta->reversed == 0)) continue;
if (!(Router::all.contains(meta->src_id) && meta->dst_id == config.local_id && meta->reserved == 0)) continue;
auto router = Router::all[meta->src_id];
auto inner = (payload + sizeof(Meta));
auto payload_length = packet_length - overhead - sizeof(Meta);
remoteSecret->decrypt(inner, payload_length);
router->decrypt(inner, payload_length);
switch (((ipv6hdr *) inner)->version) {
case 4:
if (csum((uint16_t *) inner, ((iphdr *) inner)->ihl * 4)) continue;
......@@ -72,17 +49,9 @@ void inbound(int raw, int tun) {
default:
continue;
}
// if (ip_fast_csum(inner, inner->ihl)) continue;
// std::cout << "packet_length " << packet_length
// << " tot_len " << ntohs(packet->tot_len)
// << " inner->tot_len " << ntohs(inner->tot_len)
// << " from " << inet_ntoa(address.sin_addr) << std::endl;
// if (remote_addr.sin_addr.s_addr != address.sin_addr.s_addr) {
// std::cout << "float ip: " << inet_ntoa(address.sin_addr) << std::endl;
// }
remote_addr = address;
router->remote_addr = address;
if (write(tun, inner, payload_length) < 0) {
if (write(router->tun, inner, payload_length) < 0) {
perror("inbound write");
}
}
......@@ -90,84 +59,39 @@ void inbound(int raw, int tun) {
}
// tun -> internet
void outbound(int raw, int tun) {
void outbound(int tun) {
auto router = Router::tuns[tun];
unsigned char buffer[ETH_DATA_LEN];
auto meta = (Meta *) buffer;
meta->src_id = local_id;
meta->dst_id = remote_id;
meta->reversed = 0;
meta->src_id = config.local_id;
meta->dst_id = router->config.remote_id;
meta->reserved = 0;
auto inner = buffer + sizeof(Meta);
size_t packet_length;
while ((packet_length = read(tun, inner, sizeof(buffer) - sizeof(Meta))) >= 0) {
// std::cout << "sendto: " << inet_ntoa(remote_addr.sin_addr) << std::endl;
if (!remote_addr.ss_family) continue;
localSecret->encrypt(inner, packet_length);
if (sendto(raw, buffer, packet_length + sizeof(Meta), 0, (sockaddr *) &remote_addr, sizeof(remote_addr)) <
0) {
if (!router->remote_addr.ss_family) continue;
router->encrypt(inner, packet_length);
if (setsockopt(router->raw, SOL_SOCKET, SO_MARK, &router->config.mark, sizeof(router->config.mark)) < 0) {
perror("setsockopt error");
}
if (sendto(router->raw, buffer, packet_length + sizeof(Meta), 0, (sockaddr *) &router->remote_addr,
sizeof(router->remote_addr)) < 0) {
perror("outbound write");
}
}
perror("outbound read");
}
int main(int argc, char *argv[]) {
// json data = json::parse(argv[1]);
// auto config = data.get<Config>();
//
//
// if (endpoint != nullptr) {
// addrinfo hints = {
// .ai_family = family
// };
// addrinfo *result;
//
// auto ret = getaddrinfo(endpoint, nullptr, &hints, &result);
// if (ret != 0) {
// puts(gai_strerror(ret));
// return -1;
// }
// remote_addr = *(sockaddr_storage *) result->ai_addr;
// freeaddrinfo(result); /* No longer needed */
// }
// ifreq ifr{};
// ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
// strncpy(ifr.ifr_name, dev, IFNAMSIZ);
//
// auto raw = socket(family, SOCK_RAW, proto);
// if (raw < 0) {
// perror("socket init error");
// return -1;
// }
// if (mark) {
// if (setsockopt(raw, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) {
// perror("setsockopt error");
// return -1;
// }
// }
// auto tun = open("/dev/net/tun", O_RDWR);
// if (tun < 0) {
// perror("tun init error");
// return -1;
// }
// puts(dev);
//
// if (ioctl(tun, TUNSETIFF, &ifr) < 0) {
// perror("ioctl error");
// return -1;
// }
//
// system(up);
//
// std::thread t1(inbound, raw, tun);
// std::thread t2(outbound, raw, tun);
// t1.join();
// t2.join();
json data = json::parse(argv[1]);
config = data.get<Config>();
Router::create_secret(config.local_secret, Router::local_secret);
for (const auto &item: config.routers) new Router(item);
std::vector<std::thread> threads;
for (auto &[_, router]: Router::all)threads.emplace_back(outbound, router->tun);
for (auto &[_, raw]: Router::raws)threads.emplace_back(inbound, raw);
for (auto &thread: threads) thread.join();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment