Skip to content
This repository has been archived by the owner on Oct 26, 2022. It is now read-only.

Wireguard packet support #191

Closed
wants to merge 5 commits into from
Closed

Conversation

Leo1003
Copy link
Contributor

@Leo1003 Leo1003 commented Oct 13, 2021

This contains a draft Wireguard generic netlink packet support.
There are some issues in the current codes:

  • Data converting between C struct
    Should this be handled by netlink-packet-utils?
    • struct in_addr
    • struct in6_addr
    • struct sockaddr_in
    • struct sockaddr_in6
    • struct timespec
  • Using unsafe operations to convert between bytes slice and C struct

@little-dude
Copy link
Owner

Hello @Leo1003

Apologies for not being responsive. Thanks a lot for the PR, I'll try to take a close look today.

@little-dude little-dude self-requested a review November 21, 2021 12:23
Copy link
Owner

@little-dude little-dude left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,

Thanks again for your work. I'm not a wireguard user myself, so I haven't ran the example yet.

I like the PR a lot, but I'm a bit scared of adding unsafe code, especially because I think we can avoid it here. You can see my suggested changes in your fork at Leo1003#1

What do you think?

@Leo1003 Leo1003 changed the title Draft: Wireguard packet support Wireguard packet support Nov 22, 2021
@little-dude little-dude marked this pull request as ready for review November 22, 2021 12:56
@little-dude
Copy link
Owner

@Leo1003 would you mind showing what the output of the example looks like? I don't have wireguard configured so I can't really test it.

@Leo1003
Copy link
Contributor Author

Leo1003 commented Nov 23, 2021

@Leo1003 would you mind showing what the output of the example looks like? I don't have wireguard configured so I can't really test it.

ListenPort: 43655
Fwmark: 0
IfIndex: 4
IfName: wg0
PrivateKey: (hidden)
PublicKey: grk00Lcpe2LwK8xkdq+Y5x/MiVtO7a7IeVd+z9MkJS8=
Peer:
  PublicKey: FfRQT9irrzS0LQ4wKP3hdcilNCPCHr9s6ccVyA1x410=
  PresharedKey: (hidden)
  LastHandshake: SystemTime { tv_sec: 1637654823, tv_nsec: 730473714 }
  PersistentKeepalive: 25
  TxBytes: 212
  RxBytes: 92
  Endpoint: <hidden here for privacy>
  AllowedIp: 10.0.3.0/24
  AllowedIp: 10.0.69.0/24
  AllowedIp: 10.96.0.0/16

@little-dude
Copy link
Owner

Thanks for your patience @Leo1003 :) I updated my PR. Let's rebase this and get it merged!

First, `miri` didn't like this unsafe:

```
running 3 tests
test raw::test::test_parse_sockaddr_in6_1 ... ok
test raw::test::test_parse_sockaddr_in_1 ... error: Undefined Behavior: accessing memory with alignment 1, but alignment 2 is required
   --> netlink-packet-wireguard/src/raw.rs:136:32
    |
136 |     let data: &'a T = unsafe { &*ptr };
    |                                ^^^^^ accessing memory with alignment 1, but alignment 2 is required
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

    = note: inside `raw::from_raw_slice::<libc::sockaddr>` at netlink-packet-wireguard/src/raw.rs:136:32
note: inside `raw::parse_sockaddr` at netlink-packet-wireguard/src/raw.rs:91:41
   --> netlink-packet-wireguard/src/raw.rs:91:41
    |
91  |     let csockaddr: &sockaddr = unsafe { from_raw_slice(buf)? };
    |                                         ^^^^^^^^^^^^^^^^^^^
note: inside `raw::test::test_parse_sockaddr_in_1` at netlink-packet-wireguard/src/raw.rs:160:22
   --> netlink-packet-wireguard/src/raw.rs:160:22
    |
160 |         let ipaddr = parse_sockaddr(&SOCKADDR_IN_BYTES_1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside closure at netlink-packet-wireguard/src/raw.rs:159:5
   --> netlink-packet-wireguard/src/raw.rs:159:5
    |
158 |       #[test]
    |       ------- in this procedural macro expansion
159 | /     fn test_parse_sockaddr_in_1() {
160 | |         let ipaddr = parse_sockaddr(&SOCKADDR_IN_BYTES_1).unwrap();
161 | |         assert_eq!(ipaddr, SocketAddrV4::new(Ipv4Addr::LOCALHOST, 7290).into());
162 | |     }
    | |_____^
```

Second, although in C the netlink packets are encoded en decoded by
simply transmuting slices into struct, we cannot safely to this in
Rust unless the types are _at least_ `#[repr(C)]`. If we want to go
down that path, I think we have two choices:

- using bindgen to wrap the C structs, and use the same strategy than
in C
- defining `#[repr(C)]` structs and use something like `bytemuck` to
  convert slices into structs and vice-versa.

The other netlink crates took the third option of going full rust and
manually parsing the packets. For consistency, this commit implements
this solution.
@little-dude
Copy link
Owner

I rebased and merged manually, but for some reason Github doesn't automatically mark the PR as merged.

Thanks a lot @Leo1003 ! I'll try to make a release this week.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants