syn.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #![no_std]
  2. #![no_main]
  3. use aya_bpf::{
  4. bindings::xdp_action,
  5. macros::{map, xdp},
  6. maps::Array,
  7. programs::XdpContext,
  8. };
  9. use responder_ebpf::util::*;
  10. use responder_ebpf::bindings::tcphdr;
  11. use responder_common::*;
  12. use core::mem;
  13. const TCP_HDR_LEN: usize = mem::size_of::<tcphdr>();
  14. const IPPROTO_TCP: u8 = 0x06;
  15. #[inline(always)]
  16. fn parse_tcphdr(ctx: &XdpContext, cursor: &mut usize) -> Option<*mut tcphdr> {
  17. let tcp = ptr_at_mut::<tcphdr>(&ctx, *cursor);
  18. if tcp.is_some() {
  19. *cursor += TCP_HDR_LEN;
  20. }
  21. tcp
  22. }
  23. #[xdp(name="responder")]
  24. pub fn responder(ctx: XdpContext) -> u32 {
  25. match try_responder(ctx) {
  26. Ok(ret) => ret,
  27. Err(_) => xdp_action::XDP_ABORTED,
  28. }
  29. }
  30. #[inline(always)]
  31. unsafe fn bounce_tcp(_ctx: &XdpContext, tcp: *mut tcphdr) {
  32. mem::swap(&mut (*tcp).source, &mut (*tcp).dest);
  33. mem::swap(&mut (*tcp).ack_seq, &mut (*tcp).seq); // Swap to keep checksum the same as much as possible
  34. let (ack_seq, o) = u32::from_be((*tcp).ack_seq).overflowing_add(1); // If overflow: 1's complement sum is unchanged
  35. (*tcp).ack_seq = u32::to_be(ack_seq);
  36. (*tcp).set_ack(1);
  37. (*tcp).check = !(ones_complement_add_u16(!(*tcp).check, (!o as u16) + (1 << 4)));
  38. }
  39. #[map(name = "FILTER_MAP")]
  40. static FILTER_MAP: Array<bloom_filter::ChunkType> =
  41. Array::<bloom_filter::ChunkType>::with_max_entries(bloom_filter::MAP_SIZE as u32, 0);
  42. #[inline(always)]
  43. unsafe fn matches_filter(_ctx: &XdpContext, daddr: IpAddr) -> bool {
  44. match daddr {
  45. IpAddr::V4(daddr) => {
  46. let mut res = false;
  47. for hash_offset in 0..bloom_filter::HASH_COUNT {
  48. res = true;
  49. let hash = bloom_filter::hash(daddr, hash_offset);
  50. let map_i = hash >> (bloom_filter::ADDRESS_BITS_CHUNK as u32);
  51. let chunk_i = hash & (bloom_filter::ADDRESS_MASK_CHUNK as u32);
  52. // info!(ctx, "{:ipv4} {} {} {}",daddr, hash, map_i, chunk_i);
  53. let test = if let Some(b) = FILTER_MAP.get(map_i as u32) {
  54. let word_i = chunk_i & (bloom_filter::ADDRESS_MASK_WORD as u32);
  55. let chunk_i = (chunk_i as usize) >> bloom_filter::ADDRESS_BITS_WORD;
  56. // info!(ctx, "{} [{}]", word_i, b[chunk_i]);
  57. (b[chunk_i] >> (bloom_filter::ADDRESS_MASK_WORD as u32 - word_i)) & 1 == 1
  58. } else {
  59. false
  60. };
  61. if !test {
  62. return false
  63. }
  64. }
  65. res
  66. }
  67. IpAddr::V6(_daddr) => {
  68. false // TODO
  69. }
  70. }
  71. }
  72. fn try_responder(ctx: XdpContext) -> Result<xdp_action::Type, xdp_action::Type> {
  73. let mut hdr_cursor = 0usize;
  74. let (eth, ip) = unsafe {
  75. parse_routing(&ctx, &mut hdr_cursor)
  76. .ok_or(xdp_action::XDP_PASS)?
  77. };
  78. let protocol = unsafe { l3_get_protocol(&ip) };
  79. let daddr = unsafe { l3_get_daddr(&ip) };
  80. if is_local(daddr) {
  81. // info!(&ctx, "local: pass");
  82. return Ok(xdp_action::XDP_PASS);
  83. }
  84. if unsafe { !matches_filter(&ctx, daddr) } {
  85. return Ok(xdp_action::XDP_DROP);
  86. }
  87. if protocol != IPPROTO_TCP {
  88. return Ok(xdp_action::XDP_PASS);
  89. }
  90. let tcp = parse_tcphdr(&ctx, &mut hdr_cursor).ok_or(xdp_action::XDP_PASS)?;
  91. let tcp_syn = unsafe { (*tcp).syn() };
  92. let tcp_ack = unsafe { (*tcp).ack() };
  93. // match daddr {
  94. // IpAddr::V4(ip) => info!(&ctx, "Received packet with matching daddr: {:ipv4}", ip),
  95. // IpAddr::V6(ip) => unsafe { info!(&ctx, "Received packet with matching daddr: {:ipv6}", ip.in6_u.u6_addr8) }
  96. // }
  97. // info!(&ctx, "and tcp with syn: {}, ack: {}", tcp_syn, tcp_ack);
  98. if tcp_syn == 0 || tcp_ack != 0 {
  99. return Ok(xdp_action::XDP_PASS);
  100. }
  101. unsafe {
  102. bounce_routing(&ctx,eth, ip);
  103. bounce_tcp(&ctx, tcp);
  104. }
  105. Ok(xdp_action::XDP_PASS)
  106. }
  107. #[panic_handler]
  108. fn panic(_info: &core::panic::PanicInfo) -> ! {
  109. unsafe { core::hint::unreachable_unchecked() }
  110. }