Actually, your ruleset should be fine for outbound packets: the problem is that incoming responses to those packets are getting rejected.
The main problem is this line:
-A INPUT -p tcp -m tcp --sport 1024:65535 --dport 20:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
For example, when you're attempting to run a package update, the
apt tool will send out a connection to a Debian mirror server, typically to destination port 80 for HTTP. The source port will be a random high port (certainly above 1024, let's say 12345).
The response to this packet is going to come back from the Debian mirror with the source and destination port numbers flipped around: the response's source port number will be 80 and destination port number will be 12345.
But your incoming rule will not match any incoming packets with source port lower than 1024, no matter whether they are new or already-established connections. As a result, you're sending connection requests out to port 80 but are deaf to any answers coming back from it.
I'd recommend the following as your first two INPUT rules:
-A INPUT -i lo -j ACCEPT # accept anything from the loopback interface
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
The first line will accept anything that goes through the loopback interface, or in other words, processes within your own computer talking to each other using network protocols. When the traffic comes in via the loopback interface, the source is by definition on the same computer, so there is normally little reason to block them.
The second line accepts any valid incoming responses to any outgoing connections, and anything related to them (e.g. an ICMP error packet telling you what is wrong with a particular connection attempt). If the appropriate special connection tracking helper for FTP has been activated, this line will also take care of FTP data connections, whether active or passive. Read on...
-m state match you're using is obsolete and getting deprecated; my
-m conntrack --ctstate ESTABLISHED,RELATED is basically the updated version of it.)
FTP connections will be much easier to handle if you invoke the appropriate connection tracking helper for them. This used to be automatic before, but then someone found a way to abuse the automatic helper selection and it had to be disabled.
So, tell the system that we expect any incoming connections from your network to your TCP port 21 to be valid FTP control connections:
-t raw -A PREROUTING -p tcp -s yyy.yyy.yyy.yyy/25 --dport 21 -j CT --helper ftp
As an incoming FTP control connection is established, the FTP conntrack helper will monitor any file transfer commands issued within it, and will automatically make the conntrack subsystem aware of any related FTP data connections, so that the earlier "ESTABLISHED,RELATED" rule will accept them and only them: no need to keep a wide range of ports open for potential FTP data connections any more!
When the FTP conntrack helper is in use, you'll no longer need any rules for port 20, nor any of your rules with
--sport 1024:65535 or
Attempts to hijack passive-FTP data connections will be automatically foiled too: the connection tracking subsystem will see that the hijacker's connection does not come from the same source as the FTP control connection that called for data transfer, and so the hijacking attempt will not get matched, and gets rejected by default.
If you are using FTP mirrors for your Debian updates, you'll want a similar handling for any outgoing FTP connections too. This can be done with:
-t raw -A OUTPUT -p tcp --dport 21 -j CT --helper ftp