Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with Ingress Packets Not Reflecting Changes #950

Open
FedericoRinaudi opened this issue May 17, 2024 · 1 comment
Open

Issue with Ingress Packets Not Reflecting Changes #950

FedericoRinaudi opened this issue May 17, 2024 · 1 comment

Comments

@FedericoRinaudi
Copy link

I am currently working on a project where I need to remove padding from ingress packets using an ingress classifier. The logs indicate that the packet dimensions are correctly reduced, but it appears that the changes are not propagated to the upper levels.

Upon further investigation, I suspect that the packet is being propagated to the upper levels before the eBPF program completes its execution. I experimented with returning TC_ACT_SHOT at different points in the code, and I noticed that it only takes effect in the first few lines. When placed at the end of the function, it doesn’t work as expected. Could it be an issue related to asynchronicity?

This is the function I'm having problems with:

fn try_proxy_with_tc_aya(mut ctx: TcContext) -> Result<i32, i32> {
    let eth_hdr: EthHdr = ctx.load(0).map_err(|_| TC_ACT_OK)?;
    match eth_hdr.ether_type {
        EtherType::Ipv4 => {}
        _ => return Ok(TC_ACT_OK),
    }

    let ipv4_hdr: Ipv4Hdr = ctx.load(EthHdr::LEN).map_err(|_| TC_ACT_OK)?;
    let source = u32::from_be(ipv4_hdr.src_addr);

    if source != CLIENT_IP {
        info!(&ctx, "NON CLIENT_IP: {:x}", source);
        return Ok(TC_ACT_OK);
    }

    if ipv4_hdr.proto != IpProto::Tcp.into() {
        info!(&ctx, "NON TCP");
        return Ok(TC_ACT_OK);
    }

    let ipv4_len: usize =  (ipv4_hdr.ihl() << 2).into();
    let tcp_offset = EthHdr::LEN + ipv4_len;
    let tcp_hdr: TcpHdr = ctx.load(tcp_offset).map_err(|_| TC_ACT_OK)?;
    let tcp_len: usize = (tcp_hdr.doff() << 2).into();
    let http_offset = tcp_offset + tcp_len;

    info!(&ctx, "len {}", ctx.len());

    if ctx.len() <= http_offset as u32 {
        info!(&ctx, "NO HTTP, len: {} {}", ctx.len(), ctx.data_end() as usize - ctx.data() as usize);
        return Ok(TC_ACT_OK);
    }

    ctx.adjust_room(PADDING_LEN, BPF_ADJ_ROOM_NET, 0).map_err(|_| TC_ACT_OK)?;
    ctx.store(tcp_offset, &tcp_hdr, 0).map_err(|_| TC_ACT_OK)?;

    info!(&ctx, "ADJUSTED, len: {} {}", ctx.len(), ctx.data_end() as usize - ctx.data() as usize);

    Ok(TC_ACT_OK)
}

This is the link to the project.

As I am not an expert in Aya or eBPF, I might be overlooking something crucial. Any insights or suggestions would be greatly appreciated.

@viveksb007
Copy link

I have seen something similar when I was changing checksum of packet during egress using TC egress classifier.

I was modifying the checksum of TCP header during egress which was somehow getting over-written by the kernel i believe.
I didn't found the root cause, just that my changed in packet was getting over-written somehow (as those changes were not captured when TCP dump captured the egress packet).

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

No branches or pull requests

2 participants