Hot questions for Using Ubuntu in networking

Top Java Programmings / Ubuntu / networking

Question:

I have 2 UDP broadcast servers at 192.168.1.1 broadcasting to 192.168.1.255:1234 and at 192.168.2.1 broadcasting to 192.168.2.255:1235. I have a client that must receive all packets. here is a simple code in java:

final DatagramSocket socket1, socket2;
    socket1 = new DatagramSocket(1234);
    socket2 = new DatagramSocket(1235);
    final DatagramPacket p = new DatagramPacket(new byte[10], 10);
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    socket1.receive(p);
                    System.out.println(p.getAddress());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    socket2.receive(p);
                    System.out.println();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

The problem is that the java application cannot receive from both NICs in Ubuntu. It always receives from 192.168.2.255 (eth1). All packets can be dumped using wireshark, but java cannot receive them. Also when I use exactly the same java code in TinyCore distro, there is no problem receiving packets from both NICs. What's wrong with Java in Ubuntu?


Answer:

If you want to bind to a specific address, you need to specify it:

socket1 = new DatagramSocket(1234, InetAddress.getByName("192.168.1.255"));
socket2 = new DatagramSocket(1235, InetAddress.getByName("192.168.2.255"));

Also, you shouldn't use the same DatagramPacket instance in both threads as the will definitely share the buffer, and in case of concurrent packets, the outcome is unpredictable.

Question:

In Ubuntu(OS), What java.net.preferIPv4Stack actually does and what kind of side effect it might have?

According to the Java documentation,

If IPv6 is available on the operating system, the underlying native socket will be an IPv6 socket.

For example, if java program is connecting to some other server which does not have IPv6 does this help?


Answer:

It causes the underlying native socket to be an IPv4 socket. It doesn't help in the situation you mention. It does help to resolve certain bugs.

Question:

For educational purposes I'm trying to perform a SYN flood attack on a Ubuntu 18.04 VM. I have enabled bridge mode in my VM settings and set up a web server (10.0.0.10) I can reach on my host pc (10.0.0.3) and vice versa with pings. Pinging from host to server shows Wireshark traffic on the server (request and response), pinging from server to host also shows Wireshark traffic on the server, but not on the host, even though the ping packets are correctly built.

The way I build my attack is to generate random IPs, construct TCP SYN packet and send it to the web server from my host through port 80 (open), which should send a TCP SYN/ACK packet back (I used iptables to route it back to my host pc).

If I construct a TCP packet through Pcap4J (Pcap library for Java) and subsequently send it through the handler, I see it pop up on the host Wireshark.

However, if I check the Wireshark on my VM, the packets do not arrive. The handler does not give an error and the program exits correctly and I am therefore unsure how to fix this problem.

Where is the packet dropped and what can I do to fix it? I need the packets to reach the web server VM (and the server to send them back).

Code:

    Pcaphandle send_handle;
    //nif_address is a constant of my ethernet connection defined in the file
    try {
        PcapNetworkInterface nif = Pcaps.getDevByAddress(nif_address);
        if (nif == null) {
            System.out.println("Networkinterface is null");
            return;
        }
        // Open the device and get a send_handle
        int snapshotLength = 65536; // in bytes
        int readTimeout = 50; // in milliseconds
        send_handle = nif.openLive(snapshotLength, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, readTimeout);
    } catch (PcapNativeException e) {
        System.out.println("Cannot bind NIF to variable from localhost");
        e.printStackTrace();
        return;
    }

    //Send packets, e.g. 1 packet by 5 different IPs
    for (int i = 0; i < 5; i++) {
        //generateIP() function not shown here, but is simply a randomizer and format to IP
        InetAddress src_ip = generateIP(); 

        Packet tcpPacket = constructSYNPacket(i, src_ip);
        try {
            send_handle.sendPacket(tcpPacket);
            System.out.println(send_handle.getError());
        } catch (PcapNativeException | NotOpenException e) {
            e.printStackTrace();
        }
    }

    private Packet constructSYNPacket(int packetNr, InetAddress src_address) {
    TcpPacket.Builder tcpBuilder = new TcpPacket.Builder();
    tcpBuilder
            .syn(true)
            .ack(false)
            .rst(false)
            .psh(false)
            .urg(false)
            .srcAddr(src_address)
            .srcPort(TcpPort.getInstance((short) srcPort))
            .dstAddr(dst_address)
            .dstPort(TcpPort.getInstance((short) dstPort))
            .correctLengthAtBuild(true)
            .correctChecksumAtBuild(true)
            .sequenceNumber(100000 + (packetNr*50));

    IpV4Packet.Builder ipv4Builder = new IpV4Packet.Builder();
    ipv4Builder
            .srcAddr((Inet4Address)src_address)
            .dstAddr((Inet4Address)dst_address)
            .dontFragmentFlag(true)
            .fragmentOffset((short)0)
            .ihl((byte)5)
            .correctLengthAtBuild(true)
            .correctChecksumAtBuild(true)
            .protocol(IpNumber.TCP)
            .version(IpVersion.IPV4)
            .tos((IpV4Packet.IpV4Tos) () -> (byte)0)
            .ttl((byte)100)
            .payloadBuilder(tcpBuilder);

    EthernetPacket.Builder ethBuilder = new EthernetPacket.Builder();
    ethBuilder
            .srcAddr(nif_mac)
            .dstAddr(dst_mac)
            .type(EtherType.IPV4)
            .payloadBuilder(ipv4Builder)
            .paddingAtBuild(true);

    Packet p = ethBuilder.build();

Note: I already disabled SYN cookies in the Ubuntu sysctl.


Answer:

Even though I have not found out why bridging mode did not work, I managed to make it work using a host-only adapter. Pings and packets were received both ways when I used it.