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

Goreplay not capturing actual user traffic that’s reaching varnish (port: 8983) #1246

Open
Udaykumar519 opened this issue Mar 29, 2024 · 16 comments

Comments

@Udaykumar519
Copy link

Hello all,

our application architecture on production:
client --> varnish cache (port: 8983) --> tomcat backend (port: 8984)

Using GoReplay, we are trying to redirect requests that reach our varnish that listens on 8983 port to another server.

Before redirecting, we have tried testing whether its correctly listening or not

Command used to listen:
sudo ./gor --input-raw :8983 --output-stdout

ISSUE:
However, we found that goreplay is not capturing actual user traffic from port 8983

But it's listening successfully when a request is fired explicitly from a browser or with curl.

Can someone pls help us know why its not capturing user traffic from 8983 port?

Copy link

dosubot bot commented Mar 29, 2024

Hey @Udaykumar519, great to see you back here! Hope you've been doing well.

Based on the information you've provided, there could be several reasons why GoReplay is not capturing actual user traffic from port 8983. Here are some potential causes:

  1. BPF Filter Configuration: GoReplay uses Berkeley Packet Filter (BPF) syntax for capturing traffic. If the BPF filter is not correctly set to capture traffic on port 8983, GoReplay will not capture the desired traffic. Ensure that the BPFFilter string in PcapOptions is correctly configured to include port 8983.

  2. Promiscuous Mode: For capturing traffic not destined to the host where GoReplay is running, the network interface needs to be in promiscuous mode. The Promiscuous boolean in PcapOptions controls this. If GoReplay is expected to capture all traffic on the network segment, including traffic not addressed to the host machine, ensure this option is enabled.

  3. Network Interface Configuration: GoReplay captures traffic from network interfaces. If GoReplay is not listening on the correct network interface or if the traffic on port 8983 does not pass through the interfaces GoReplay is monitoring, it will not capture the traffic. Ensure GoReplay is configured to listen on the correct network interface(s) where traffic to and from port 8983 passes.

  4. Firewall or Security Group Settings: External factors such as firewall rules or security group settings might be preventing GoReplay from capturing traffic on port 8983. Ensure that there are no such external restrictions on the network where GoReplay is deployed.

  5. Kubernetes Environment: If you're running GoReplay in a Kubernetes environment, network policies or the CNI (Container Network Interface) plugin configuration might restrict the capture of traffic. Ensure that the network policies allow for the capturing of traffic on port 8983 and that GoReplay is deployed in a manner that it can monitor the desired traffic.

  6. Engine Type: The EngineType in the configuration determines the method used for capturing traffic. Different engines (e.g., EnginePcap, EngineRawSocket) have different capabilities and limitations. Ensure that the engine you're using supports capturing the type of traffic you're interested in.

Without more specific details on how GoReplay is configured and deployed, these are general areas to investigate. Ensure that GoReplay's configuration aligns with the network topology and the specifics of the traffic you're trying to capture.

For more information, you can refer to the GoReplay source code, specifically the internal/capture/capture.go file, which contains the implementation details of the traffic capturing functionality.

If you could provide more details about your GoReplay configuration and deployment, it would be easier to diagnose the issue. For example, are there any error messages in the GoReplay logs? What is the exact command you're using to start GoReplay? What is the network topology where GoReplay is deployed?

Sources

About Dosu

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

@Udaykumar519
Copy link
Author

In the architecture mentioned above, i would like to give some more details which might help

Here, varnish i mentioned is behind Load balancer, you can assume as below
client ---> Load Balancer --> varnish ---> tomcat backend

pinpointed issue:
Whenever the user request is fired on varnish directly, goreplay is capturing it

But when the user request comes to varnish through Load Balancer, gor is not capturing it

@buger
Copy link
Owner

buger commented Mar 29, 2024

@Udaykumar519 if you can capture "pcap" file using tcpdump it can help replicate the issue, and fix it. Thanks!

@Udaykumar519
Copy link
Author

@buger May i know probable issues due to which goreplay is not listening when the request is reached through Load Balancer?

so that we will get some direction to debug

@buger
Copy link
Owner

buger commented Apr 1, 2024

I believe there could be issue with network interface mismatch, I would recommend trying this argument: --input-raw-bpf-filter "dst port 8983"

@Udaykumar519
Copy link
Author

Heyy @buger !

Thanks, its listening now when used below command:
sudo ./gor --input-raw :8983 --input-raw-bpf-filter "dst port 8983" --output-stdout

One small observation:
It seems, its also listening outgoing requests from the server, which uses 8983 port, which is not as expected

@buger
Copy link
Owner

buger commented Apr 1, 2024

@dosu-bot any suggestion on message above? Can you adjust bpf filter, so it will not listen of outgoing requests?

Copy link

dosubot bot commented Apr 1, 2024

To capture only the incoming traffic on port 8983 and exclude the outgoing traffic, you can refine your BPF filter with the command:

sudo ./gor --input-raw :8983 --input-raw-bpf-filter "dst port 8983 and inbound" --output-stdout

This command ensures that GoReplay listens only to incoming requests directed to port 8983, effectively filtering out the outgoing requests from the server on the same port. The dst port 8983 part of the filter specifies that the destination port should be 8983, and inbound specifies that only inbound traffic is captured.

It's important to note that the effectiveness of this command can depend on your specific network setup and the platform GoReplay is running on. If you encounter any issues or the traffic is not filtered as expected, you might need to adjust the BPF expression to better suit your environment.

Regarding the options --input-raw-bpf-filter and --bpf-filter, it appears that --input-raw-bpf-filter is the correct option to use for specifying BPF filters in GoReplay, as per the current documentation and codebase. This option is specifically designed to apply BPF filters to the traffic captured by GoReplay.

If you have further questions or need additional clarification, feel free to ask.

Sources

About Dosu

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

@Udaykumar519
Copy link
Author

Thanks a lot, @buger
Now, its working as expected!

Asking out of curiosity, can you pls help me understand difference between below 2 goreplay commands?
like in terms of network interfaces, how goreplay is capturing packets

  1. sudo ./gor --input-raw :8983 --input-raw-bpf-filter "dst port 8983 and inbound" --output-stdout

  2. sudo ./gor --input-raw :8983 --output-stdout

@buger
Copy link
Owner

buger commented Apr 1, 2024

@dosu-bot i may need a bit of your help here. Check the source code and show me the format of bpf filter which it generates by default, with example. And use it to explain difference between those 2 commands.

Copy link

dosubot bot commented Apr 1, 2024

The difference between the two GoReplay commands you've mentioned primarily lies in the use of the Berkeley Packet Filter (BPF) syntax to specify which traffic to capture.

  1. The command sudo ./gor --input-raw :8983 --input-raw-bpf-filter "dst port 8983 and inbound" --output-stdout uses a BPF filter to capture only inbound traffic destined for port 8983. This is achieved by specifying "dst port 8983 and inbound" in the BPF filter, which tells GoReplay to listen for packets where the destination port is 8983 and the direction is inbound, effectively filtering out any outbound traffic from the server on the same port.

  2. On the other hand, the command sudo ./gor --input-raw :8983 --output-stdout without specifying a BPF filter captures all packets that GoReplay has permission to see on port 8983, including both inbound and outbound traffic. In the absence of a specific BPF filter, GoReplay does not apply any additional filtering criteria, capturing all traffic it can access on the specified port.

Regarding the default behavior of GoReplay when no --input-raw-bpf-filter argument is provided, it typically captures all packets on the specified port(s) without additional filtering, unless default filtering criteria are defined by the tool itself. However, the exact default BPF filter format GoReplay uses in this scenario is not explicitly documented.

GoReplay utilizes the capture package for packet capturing, with the EnginePcap engine being a key component in this process. The --input-raw argument initializes a RAWInput instance with specific network address and configuration, including the packet capture engine and protocol to capture. The --input-raw-bpf-filter argument allows users to directly specify a BPF string, which is applied to the pcap handle when capturing packets. This is managed in the codebase through the PcapOptions struct, which contains a BPFFilter field for holding the user-provided BPF filter string.

It's important to note that GoReplay does not explicitly differentiate between inbound and outbound traffic when applying the BPF filter. The directionality must be specified as part of the BPF expression itself, as seen in the first command. The SetBPFFilter function applies the compiled BPF filter to the socket, filtering packets based on the specified criteria without considering the direction of the traffic.

This explanation should help you understand how GoReplay captures packets and the impact of specifying a BPF filter on the traffic that is captured. If you have further questions or need more information, feel free to ask.

Sources

About Dosu

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

@buger
Copy link
Owner

buger commented Apr 1, 2024 via email

Copy link

dosubot bot commented Apr 1, 2024

The difference between the two GoReplay commands you've inquired about essentially boils down to how they filter the network traffic they capture, particularly in terms of specifying which packets to listen to.

  1. Command with BPF Filter:

    sudo ./gor --input-raw :8983 --input-raw-bpf-filter "dst port 8983 and inbound" --output-stdout

    This command explicitly uses a Berkeley Packet Filter (BPF) to capture only the inbound traffic that is destined for port 8983. The BPF filter "dst port 8983 and inbound" instructs GoReplay to listen for packets where the destination port is 8983 and the direction is inbound. This effectively filters out any outbound traffic from the server on the same port. The inclusion of the BPF filter provides a fine-grained control over the traffic that GoReplay captures, allowing it to focus on specific types of packets based on their attributes and direction.

  2. Command without BPF Filter:

    sudo ./gor --input-raw :8983 --output-stdout

    This command captures all packets that GoReplay has permission to see on port 8983, without any additional filtering. It captures both inbound and outbound traffic because it does not specify a BPF filter to restrict the captured traffic. In the absence of a specific BPF filter, GoReplay does not apply any additional filtering criteria, capturing all traffic it can access on the specified port.

The key difference lies in the use of the --input-raw-bpf-filter option, which allows for specifying a BPF filter to refine the captured traffic. When you specify a BPF filter, you can narrow down the traffic to exactly what you're interested in, such as inbound requests to a specific port, which is particularly useful in complex network setups or when monitoring specific types of traffic.

Without a BPF filter, GoReplay captures a broader range of packets, which might include traffic not relevant to your monitoring or analysis goals. This can lead to capturing more data than necessary, potentially increasing the overhead and making it harder to focus on the traffic of interest.

In summary, the use of a BPF filter with GoReplay provides a powerful mechanism to precisely define the scope of traffic capture, enabling more targeted monitoring and analysis of network traffic.

About Dosu

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

@Udaykumar519
Copy link
Author

Udaykumar519 commented Apr 1, 2024

Its quite contradictory when tested with and without bpf filter

let me know if i am missing anything here

when tried below command:
sudo ./gor --input-raw :8983 --output-stdout

output it given:
Interface: eth0 . BPF Filter: ((tcp dst port 8983) and (dst host 10.128.193.4 or dst host fe80::4001:aff:fe80:c104))
Interface: lo . BPF Filter: ((tcp dst port 8983) and (dst host 127.0.0.1 or dst host ::1))

Here, its not listening requests from load balancer but ideally as per goreplay reference it should listen to whole traffic

when tried below command:
sudo ./gor --input-raw :8983 --input-raw-bpf-filter "dst port 8983 and inbound" --output-stdout

Output it given:
Interface: eth0 . BPF Filter: dst port 8983 and inbound
Interface: lo . BPF Filter: dst port 8983 and inbound

Here, we have used explicit filter, here its working as expected when received traffic from load balancer

@Udaykumar519
Copy link
Author

any corrections or confirmations here?

@buger
Copy link
Owner

buger commented Apr 2, 2024

Yes I this it is correct. They key part here is probably this line which makes the difference dst host 10.128.193.4 or dst host fe80::4001:aff:fe80:c104). Packet target IP and Interface IP somehow mismatch 🤔

Can you run the following command: sudo tcpdump -i any -n dst port 8983 and post here a few lines? It will not expose any senstivie data, just some packet metadata.

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