I have a Linux router on which I use CONFIG_IP_NF_QUEUE, iptables userland and Perl module IPTables::IPv4::IPQueue to examine H323 - H.225 packets and pass or drop then. I have need to not only accept or drop the packet but to modify it, to be more specific I would like to change the IP address of the MCU (in the packet) returned from the H323 gatekeeper to the client.
This would require me to examine the TCP packet body and change the IP address in the packet body. Anyone know how can I accomplish this? Is there any open source layer 7 router capable of doing this?
In the old days I've used "ip masquerade" to do something similar to what you are describing.
http://www.tldp.org/HOWTO/IP-Masquerade-HOWTO/supported-client-software.html
But the best solution is to place a gatekeeper as a proxy. In that way you are not fooling the protocol, you are actually remaking the call.
I would look for gnugk routed mode here:
http://www.gnugk.org/h323-proxy.html
If you have already got the IP packet, which from your statement you have succeeded in doing so, I don't see the problem to change the IP address of the packet before passing it on.
Just do some bits manipulation to change the IP address in IP header (also update the IP checksum). Also note that you have to update the TCP header checksum as its calculation involves a pseudo-header that includes IP addresses.
Just read RFC 791 and RFC 793 would give you an idea on how to do this. It's pretty straightforward.
Related
I'm working on Linux 4.13.x. And I'm considering to send a packet response in the kernel.
Consider an echo TCP or UDP server running in the userland and there is also another node running a TCP or UDP client. Clients are sending requests to the server. I want to send the packet response back to the client without any involvement of server application running at userspace.
Here is my thoughts about this problem:
I started thinking how it is possible and I come across to a solution like netfilter. If I can capture the packets in NF_INET_PRE_ROUTING and then try to swap the source and destination IP addresses of IP header and also swapping the ports in the TCP header, then according to this answers and this presumably modified packet should be forwarded to the originator throughout the routing system.
Actually, I tried this scenario and it seems it is not possible to do so from netfilter hooks, however, I'm not sure of it. I thought that it is not working since it has problem with checksums because I'm manipulating packets so I did another experiment to figure this issue out. I just change the packet data and everything worked well. I think checksums don't have any problem since they will be check at NIC while receiving and also same situation while sending so manipulation in between doesn't make anything wrong. I also activate the IPv4 forwarding at the server host(sysctl.config) still nothing changes.
I don't want to create new packet, I only want to alter this packet and send it back. There is another similar question which is creating another packet. Moreover, I'm just thinking why this scenario is not working? But based on the netfilter's architecture it should work.
Thank you
I am also working on this, actually kernel validate the source ip address after ip_rcv function in NF_HOOK which check the source ip address. So just try below command:-
sudo sysctl -w "net.ipv4.conf.all.rp_filter=0"
after doing this also disable your interface from which you send and receive packet just like below:-
sudo sysctl -w "net.ipv4.conf.enp2s0.rp_filter=0"
Working with Linux.
Given a specific destination IP address, I need to populate the ARP cache with its next hop MAC address and interface.
Other mechanism in my software project will take this MAC address and push it to an FPGA.
If I open a TCP connection to the address it will be resolved and TCP handshake packets are sent. If I open a UDP socket and 'connect' it to the address it will not be resolved. If I send a single packet over the connected UDP socket it is resolved.
arp(7) documentation explains this: "... Requests are sent only when there is data queued for sending".
I can't call the 'arp' utility directly.
My question: is there a way to convince the system to populate an address by sending ARP in the background without the need for actually sending a packet?
I hope for some ioctl or setsockopt.
I prefer a generic solution that will also work for IPv6 neighbor resolution.
Thanks,
Gur
I need to generate an Ethernet header that includes the destination MAC address, (since libnfnetlink gives only the IP header before prerouting takes place), the outgoing interface number is also known, so the lookup can be made in the correct network.
What's the library/function to resolve the MAC address from an IP address?
It's unclear why you need the MAC address, since that's usually handled for you at a lower level.
However, assuming your target is on your local Ethernet segment, you can use the arp command to look up values in the local cache. If the value is not cached... Well, that's a problem. Perhaps arping would help...
(Normally you'd send a packet to, for example, IP address 10.10.10.10, and your system would send an ARP packet out querying who-has 10.10.10.10, and a response would come back from that target system with its MAC address, and then it would be cached. (You can watch this happening with tcpdump.) Or when a system comes on line it would send out a broadcast message informing everyone else of its MAC address. Naturally, if your destination is on another Ethernet segment, you're routing to a gateway rather than directly to the destination, and no destination-MAC address is available.)
You might read further at:
http://linux.die.net/man/8/arp
http://linux.die.net/man/8/arping
http://linux.die.net/man/7/arp
http://www.kernel.org/doc/man-pages/online/pages/man7/arp.7.html
Obviously you can only find the MAC address for directly connected IP addresses, but there's no platform-independent way of doing it. On Linux, you can look in /proc/net/arp after sending something to the target to trigger the kernel to send the ARP.
Edit to add you could also use the SIOCGARP ioctl() though that just looks in the ARP cache, so it won't send an ARP if there isn't one already there.
Otherwise, you would have to craft your own ARP request packet. You could probably reuse a bunch of code from arping if you go that route.
You cannot in general get the MAC address from the IP address, and in fact as IP can run on data link protocols other than ethernet, some IP addresses have no corresponding MAC address.
The MAC address is only available and only relevant on the same ethernet segment. On that segment, it can be retrieved by an ARP request.
I was wondering if there is any way to tune (on a linux system), the MTU for a given socket. (To make IP layer fragmenting into chunks smaller that the actual device MTU).
When I say for a given socket, I don't mean programatically in the code of the application owning the socket but rather externally, for example via a sysfs entry.
If there is currently no way do that, do you have any ideas about where to hook/patch in linux kernel to implement such a possibility ?
Thanks.
EDIT: why the hell do I want to do that ?
I'm doing some Layer3-in-Layer4 (eg: tunneling IP and above through TCP tunnel) tunneling. Unlike VPN-like solutions, I'm not using a virtual interface to achieve that. I'm capturing packets using iptables, dropping them for their normal way and writing them to the tunnel socket.
Think about the case of a big file transfer, all packets are filled up to MTU size. When I tunnel them, I add some overhead, leading in every original packet to produce two tunneled packets, it's under-optimal.
If the socket is created such that DF set on outgoing packets you might have some luck in spoofing (injecting) an ICMP fragmentation needed message back at yourself until you end up with the desired MTU. Rather ugly, but depending on how desperate you are it might be appropriate.
You could for example generate these packets with iptables rules, so the matching and sending is simple and external to your application. It looks like the REJECT target for iptables doesn't have a reject-with of fragmentation needed though, it probably wouldn't be too tricky to add one.
The other approach, if it's only TCP packets you care about is you might have some luck with the socket option TCP_MAXSEG or the TCPMSS target if that's appropriate to your problem.
For UDP or raw you're free to send() packets as small as you fancy!
Update:
Based on the "why would I want to do that?" answer, it seems like fragmenting packets if DF isn't set or raising ICMP "fragmentation needed" and dropping would actually be the correct solution.
It's what a more "normal" router would do and provided firewalls don't eat the ICMP packet then it will behave sanely in all scenarios, whereas retrospectively changing things is a recipe for odd behaviour.
The iptables clamp mss is quite a good fix for TCP over this "VPN" though, especially as you're already making extensive use of iptables it seems.
MTU is a property of a link, not socket. They belong to different layers of the stack. That said TCP performs Path MTU discovery during the three-way handshake and tries very hard to avoid fragmentation. You'll have hard time making TCP send fragments. With UDP the easiest is to force some smallish MTU on an interface with ifconfig(8) and then send packets larger then that value.
Imagine a user sitting at an Ethernet-connected PC. He has a browser open. He types "www.google.com" in the address bar and hits enter.
Now tell me what the first packet to appear on the Ethernet is.
I found this question here: Interview Questions on Socket Programming and Multi-Threading
As I'm not a networking expert, I'd like to hear the answer (I'd assume it is "It depends" ;) ).
With a tool like Wireshark, I can obviously check my own computers behaviour. I'd like to know whether the packets I see (e.g. ARP, DNS, VRRP) are the same in each ethernet configuration (is it dependent on the OS? the driver? the browser even :)?) and which are the conditions in which they appear. Being on the data-link layer, is it maybe even dependent on the physical network (connected to a hub/switch/router)?
The answers that talk about using ARP to find the DNS server are generally wrong.
In particular, IP address resolution for off-net IP addresses is never done using ARP, and it's not the router's responsibility to answer such an ARP query.
Off-net routing is done by the client machine knowing which IP addresses are on the local subnets to which it is connected. If the requested IP address is not local, then the client machine refers to its routing table to find out which gateway to send the packet to.
Hence in most circumstances the first packet sent out will be an ARP request to find the MAC address of the default gateway, if it's not already in the ARP cache.
Only then can it send the DNS query via the gateway. In this case the packet is sent with the DNS server's IP address in the IP destination field, but with the gateway's MAC address on the ethernet packet.
You can always download wireshark and take a look.
Though to spoil the fun.
Assuming, the IP address of the host is not cached, and the MAC address of the DNS server is not cached, the first thing that will be sent will be a broadcast ARP message trying to find out the MAC address of the DNS server (which the router will respond to with its own address).
Next, the host name will be resolved using DNS. Then the returned IP address will be resolved using ARP (again the router will respond with its own address), and finally, the HTTP message will actually be sent.
Actually, it depends on a variety of initial conditions you left unspecified.
Assuming the PC is running an operating system containing a local DNS caching resolver (mine does), the first thing that happens before any packets are sent is the cache is searched for an IP address. This is complicated, because "www.google.com" isn't a fully-qualified domain name, i.e. it's missing the trailing dot, so the DNS resolver will accept any records already in its cache that match its search domain list first. For example, if your search domain list is "example.com." followed by "yoyodyne.com." then cached resources matching the names "www.google.com.example.com." "www.google.com.yoyodyne.com." and finally "www.google.com." will be used if available. Also note: if the web browser is one of the more popular ones, and the PC is running a reasonably current operating system, and the host has at least one network interface with a global scope IPv6 address assigned (and the host is on a network where www.google.com has AAAA records in its DNS horizon), then the remote address of the server might be IPv6 not IPv4. This will be important later.
If the remote address of the Google web server was locally cached in DNS, and the ARP/ND6 cache contains an entry for the IPv4/IPv6 address (respectively) of a default router, then the first transmitted packet will be a TCP SYN packet sourced from the interface address attached to the router and destined for the cached remote IPv4/IPv6 address. Alternatively, the default router could be reachable over some kind of layer-2 or layer-3 tunnel, in which case, the SYN packet will be appropriately encapsulated.
If the remote address of the Google web server was not locally cached, then the host will first need to query for the A and/or AAAA records in the DNS domain search list in sequence until it gets a positive response. If the first DNS resolving server address in the resolver configuration is in one of the local IPv4 subnet ranges, or in a locally attached IPv6 prefix with the L=1 bit set in the router advertisement, and the ARP/ND6 cache already contains an entry for the address in question, then the first packet the host will send is a direct DNS query for either an A record or a AAAA record matching the first fully-qualified domain name in the domain search list. Alternatively, if the first DNS server is not addressable on-link, and a default router has an ARP/ND6 cache entry already, then the DNS query packet will be sent to the default router to forward to the DNS server.
In the event the local on-link DNS server or a default router (respectively, as the case above may be) has no entry in the ARP/ND6 cache, then the first packet the host will send is either an ARP request or an ICMP6 neighbor solicitation for the corresponding address.
Oh, but wait... it's even more horrible. There are tweaky weird edge cases where the first packet the host sends might be a LLMNR query, an IKE initiation, or... or... or... how much do you really care about all this, buckaroo?
It depends
Got that right. E.g. does the local DNS cache contain the address? If not then a DNS lookup is likely to be the first thing.
If the host name is not in DNS cache nor in hosts file, first packet will go to DNS.
Otherwise, the first packet will be HTTP GET.
Well, whatever you try to do, the first thing happening is some Ethernet protocol related data. Notably, Ethernet adapters have to decide whether the Ethernet bus is available (so there's some collision detection taking place here)
It's hard to answer your question because it depends a lot on the type of ethernet network you're using. More information on Ethernet transmission can be found here and here