I've finally figured this out!
The issue was with my udp client on my laptop that was sending(as expected) from a random local port.
Ardupilot sends and receives from a single udp port which is randomly assigned at startup. It also expects the GCS to do the same(on port 6000). You can't have the server listening on port 6000 and the client sending from another port, GCS always has to send and receive from port 6000(or which ever telemetry port you use to launch autopilot).
So the solution is to use the server to listen and send the messages using port 6000.
I've prepared a simple NodeJs test script, in case anybody needs it, you can find it here:
These are the steps I followed:
1. Get mavlink from Github and use the included python script to generate the library(whatever language you use)
git clone firstname.lastname@example.org:mavlink/mavlink.git
python -m mavgenerate
If you get an error, it's probably because you are missing the python future library.
pip install future
2. include the generated mavlink library in your app
3. Create a UDP server listening on port 6000
4. Wait to get a valid MAVLink message(HEARTBEAT) from the drone and to store the UDP remote port
5. Send MAVLink messages from the server(port 6000) to the drone.