Post

Replies

Boosts

Views

Activity

How to add (another) default route to link layer address?
Greetings, I am trying to mimic what the official WireGuard client (available on AppStore, source code is publicly available) does regarding the routing tables. The client uses NetworkExtension framework. When a VPN connection is established with all traffic routed through WireGuard (AllowedIPs = 0.0.0.0/0), the routing table is amend with something like this: Destination Gateway RT_IFA Flags Refs Use Mtu Netif Expire default link#36 10.10.10.2 UCSg 114 0 1420 utun7 10.10.10.2 10.10.10.2 10.10.10.2 UH 0 10 1420 utun7 224.0.0/4 link#36 10.10.10.2 UmCS 0 0 1420 utun7 255.255.255.255/32 link#36 10.10.10.2 UCS 0 0 1420 utun7 Please note that another default route exists to the working Ethernet interface, but I have not mentioned it above. I would like to do something similar for wireguard-go (open source WireGuard implementation written in Go), in particular start it, assign an IP address, then add the routes. sudo env LOG_LEVEL=debug wireguard-go -f utun sudo ifconfig utun5 10.10.10.2 10.10.10.2 netmask 255.255.255.255 Here is the code fragment written in C which suppose to add default route (0.0.0.0/0) to the link layer address: void add_link_route() { struct { struct rt_msghdr hdr; struct sockaddr_in dest; struct sockaddr_dl gateway; struct sockaddr_in netmask; } rt; memset(&rt, 0, sizeof(rt)); int sockfd = socket(PF_ROUTE, SOCK_RAW, 0); if (sockfd == -1) { perror("socket"); return; } unsigned int if_index = if_nametoindex("utun5"); rt.hdr.rtm_msglen = sizeof(rt); rt.hdr.rtm_version = RTM_VERSION; rt.hdr.rtm_type = RTM_ADD; rt.hdr.rtm_index = if_index; rt.hdr.rtm_flags = RTF_UP | RTF_STATIC | RTF_CLONING; rt.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; rt.hdr.rtm_seq = 1; rt.hdr.rtm_pid = getpid(); rt.dest.sin_len = sizeof(struct sockaddr_in); rt.dest.sin_family = AF_INET; rt.dest.sin_addr.s_addr = INADDR_NONE; rt.gateway.sdl_len = sizeof(struct sockaddr_dl); rt.gateway.sdl_family = AF_LINK; rt.gateway.sdl_index = if_index; rt.gateway.sdl_type = IFT_PPP; rt.netmask.sin_len = sizeof(struct sockaddr_in); rt.netmask.sin_family = AF_INET; rt.netmask.sin_addr.s_addr = INADDR_NONE; if (write(sockfd, &rt, sizeof(rt)) == -1) { perror("write"); } close(sockfd); } But, when executed, write() returns EEXIST (File exists) error, meaning, the default route cannot be overwritten (because another default route exists which points to the existing Ethernet interface). At this point I have no idea how the routes could be created successfully inside NetworkExtension, and I would like to do the same. For comparison, there is another case when all traffice is not routed through the VPN. Then, the routes are created like this: Destination Gateway RT_IFA Flags Refs Use Mtu Netif Expire default link#36 10.10.10.2 UCSIg 0 0 1420 utun7 10.10.10.2 10.10.10.2 10.10.10.2 UH 0 0 1420 utun7 224.0.0/4 link#36 10.10.10.2 UmCSI 0 0 1420 utun7 255.255.255.255/32 link#36 10.10.10.2 UCSI 0 0 1420 utun7 The difference is that now the scope is bound to the network interface. And in such case, my C code succeeds, providing I add RTF_IFSCOPE flag to rtm_flags. I would appreciate if someone helped me with this problem.
1
0
187
Sep ’24