How to route outgoing traffic going to port 25 into different gateway?

Hi!

First of all I have to say that I am a complete-complete newbie in networking, routing and similar things. So maybe my question is invalid or just elementary.

I have two machines, one of which is a VPN (Wireguard) server, let's call it 'server', and another one is a client ('client'). On the client, I have a wg0 tunnel interface and all the outgoing traffic is going through it. But I would like mail-traffic (port 25) to be routed not into VPN server, but into another gateway on the client. How can I do that? Now, the point is not in mail and port 25, it could be any port (say, 22 for ssh), I just want to understand the general principle.

I did a quick research, but I found only answers for Linux distros (with ip rule), but as I can see, it can't be applied to FreeBSD. Honestly, I'm not even sure what tool should I use for that: is this a routing (route) or a firewall (pf) responsibility? It seems that I should use route, but I can't find a way to route a particular port...

ifconfig
Code:
em0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
    options=4e524bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,LRO,WOL_MAGIC,VLAN_HWFILTER,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6,HWSTATS,MEXTPG>
    ether f0:de:f1:ca:7b:fc
    inet 192.168.1.90 netmask 0xffffff00 broadcast 192.168.1.255
    media: Ethernet autoselect (1000baseT <full-duplex>)
    status: active
    nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
lo0: flags=1008049<UP,LOOPBACK,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu 16384
    options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
    inet 127.0.0.1 netmask 0xff000000
    inet6 ::1 prefixlen 128
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
    groups: lo
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
wg0: flags=1008043<UP,BROADCAST,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu 1420
    options=4080000<LINKSTATE,MEXTPG>
    inet 10.66.66.2 netmask 0xffffffff broadcast 10.66.66.2
    inet6 fd42:42:42::2 prefixlen 128
    groups: tun
    nd6 options=101<PERFORMNUD,NO_DAD>
    Opened by PID 35172

netstat -rn4
Code:
Routing tables

Internet:
Destination        Gateway            Flags         Netif Expire
0.0.0.0/1          link#3             US              wg0
default            192.168.1.1        UGS             em0
10.66.66.2         link#2             UH              lo0
83.217.222.2       192.168.1.1        UGHS            em0
127.0.0.1          link#2             UH              lo0
128.0.0.0/1        link#3             US              wg0
192.168.1.0/24     link#1             U               em0
192.168.1.90       link#2             UHS             lo0

If I understand correctly (I'm a newbie), 0.0.0.0/1 says all the outgoing traffic to go into wg0 interface. And I want a traffic for port 25 to go into default gateway (192.168.1.1).

Sorry for clumsy question...
Thank you in advance.
 
ipfw/pf or fibs neither is very straight forward.
but assuming all your talk with your smtp host is just smtp you can route add smtp.domain.net 192.168.1.1 and thats it
 
Like people have already pointed out, you need something more complex than just routing for this. It can easily be done using for example pf() but the learning curve if quite steep if you're a newbie.

But anyways, here is a example on a redirect rule for smtp.
Code:
rdr pass proto tcp from any to any port 25 -> <smtp server> port 25

But as already suggested, there could be a number of other ways to solve your problem. If you could elaborate on your specific needs maybe we could help further.
 
Thank you very much guys!

> If you could elaborate on your specific needs maybe we could help further

The VPN server in my case is itself a VDS, where ports like 25, 465 and 587 are blocked by the provider. Now, I can ask to unlock them, but it looks more interesting for me to exclude all the traffic that goes into these ports from being passed through VPN and instead be sent as it would have been sent if I dind't have VPN whatsoever. Like that :)

Code:
rdr pass proto tcp from any to any port 25 -> <smtp server> port 25
petan thank you for the example! Though, as you can see, I don't have a particular smtp server as destination. It's more like I would like to have the situation when my system tries to send something into 25 port (no matter the destination IP address), these things would be handled by my default gateway instead of wg0 in my case.

Again, I'm sorry, I'm inexperienced in this area and probably understand things wrongly.
 
Though, as you can see, I don't have a particular smtp server as destination. It's more like I would like to have the situation when my system tries to send something into 25 port (no matter the destination IP address), these things would be handled by my default gateway instead of wg0 in my case.

Again, I'm sorry, I'm inexperienced in this area and probably understand things wrongly.
Ah, I see your problem!

Im not sure I have a solution for your atm.

Maybe I could describe a similar problem I have at home. My ISP block mail traffic so I have set up a smtp server in my local network using dma().

I then tell all my local servers to use that server as their SMTP host. The dma server is then configured to use a specific smarthost for all emails.

In your case you could run a smtp server on your VPN server and then tell your VPC-host to use that server as smarthost.

Hm, this description got messy. Hopefully you got something out of it.
 
just add a static route to the smtp server via the gateway that you want.

for example
route add 8.8.8.8 192.168.1.1

So if your SMTP server is 8.8.8.8 all traffic to it will be routed via your em0 192.168.1.1 instead of the wg0 interface.
 
aiui the OP wants traffic to any IP on port 25 to go out a different interface. the route suggestions do not discriminate on port, and only applies to a single outgoing IP.
 
Maybe I could describe a similar problem I have at home. My ISP block mail traffic so I have set up a smtp server in my local network using dma().

I then tell all my local servers to use that server as their SMTP host. The dma server is then configured to use a specific smarthost for all emails.
Unfortunately, dma(8) does not listen on port 25.
dma is not intended as a replacement for real, big MTAs like sendmail(8) or postfix(1). Consequently, dma does not listen on port 25 for incoming connections.
In your case you could run a smtp server on your VPN server and then tell your VPC-host to use that server as smarthost.
I'm a fan of postfix(1). Looks like it should work out of the box for what you want:

The pf.conf(5) rule then becomes:
Code:
rdr pass proto tcp from any to any port 25 localhost port 25
 
aiui the OP wants traffic to any IP on port 25 to go out a different interface. the route suggestions do not discriminate on port, and only applies to a single outgoing IP.
yeah but unless you are.a spam farm operator 1-3 smtp hosts will do :). so the route solution is still ok
 
eh, we've wanted this configuration before when we were on a residential line. we ended up getting business class service and asking our ISP to unblock ports instead.
 
Thank you for your answers folks! I will look at them more carefully tomorrow and try them out.

But now I'm curious: why the idea 'route _all_ trafic for port 25 through a different gateway' is not implementable (or at least, not very easily)? I mean, it sounds simple (just in logical sense), and it's now just interesting to me why isn't that possible? Why is it possible for a particular host, but not for _any_ host? Maybe some of you know technical details that make it difficult? That would be interesting to read.
 
port 25 is off limits for residential type connection. even if you are a small or medium biz is better to fw your mail via the sendgrids of the world then fighting every motherfscker who uses some bullshit-know-it-all.dnsblbollocks.org and blocks you because you appear to be part of the wrong kind of ip block. the reality is that if you are not msft or goog you are probably fscked
 
But now I'm curious: why the idea 'route _all_ trafic for port 25 through a different gateway' is not implementable (or at least, not very easily)?
it's easily implementable with rdr rules in pf or ipfw — it just isn't implementable with route because IP routing is literally unaware of TCP ports.
 
Unfortunately, dma(8) does not listen on port 25.


I'm a fan of postfix(1). Looks like it should work out of the box for what you want:

The pf.conf(5) rule then becomes:
Code:
rdr pass proto tcp from any to any port 25 localhost port 25
Yes. My description was not very clear. On my network all machines run dma locally to deliver mail to my postfix server. Postfix then delivers mails towards its final destination.
 
But now I'm curious: why the idea 'route _all_ trafic for port 25 through a different gateway' is not implementable (or at least, not very easily)?
It depends on what you mean by "route". If you mean it in the colloquial sense of "send", then it sure is implementable, as we've shown in this thread. If you mean it in the technical sense of an IP route, then no, routing happens at a layer below TCP that doesn't know or care anything about what protocols are running above it.

Why is it possible for a particular host, but not for _any_ host?
I'm not sure why you think that. If you put the redirection rule in your default gateway, all traffic from any host will be affected. I do this very thing in my Openbsd gateway/firewall:
Code:
pass in quick on $int_if proto tcp from any to any port 25 rdr-to 127.0.0.1 port 2525
 
ipfw fwd 192.168.1.1 tcp from me to any 25 is what you want
I tried this one:
Code:
# ipfw add fwd 192.168.1.1 tcp from any to any 25 via em0
# ipfw show
00100      0        0 allow ip from any to any via lo0
00200      0        0 deny ip from any to 127.0.0.0/8
00300      0        0 deny ip from 127.0.0.0/8 to any
00400      0        0 deny ip from any to ::1
00500      0        0 deny ip from ::1 to any
00600      2      232 allow ipv6-icmp from :: to ff02::/16
00700      0        0 allow ipv6-icmp from fe80::/10 to fe80::/10
00800      0        0 allow ipv6-icmp from fe80::/10 to ff02::/16
00900      0        0 allow ipv6-icmp from any to any icmp6types 1
01000      0        0 allow ipv6-icmp from any to any icmp6types 2,135,136
01200      0        0 fwd 192.168.1.1 tcp from any to any 25 via em0
65535      0        0 count ip from any to any not // orphaned dynamic states counter
65535 138722 45135352 allow ip from any to any

But still, when wireguard (VPN) is active, and I try to access port 25, the rule seems to be ignored:
Code:
# telnet smtp.gmail.com 25
Trying 142.250.102.108...
... and it hangs ...

I also enabled logging for ipfw:
Code:
options IPFIREWALL
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=5

/etc/rc.conf
Code:
firewall_enable="YES"
firewall_logging="YES"

But /var/log/security is empty:
Code:
Mar  8 10:31:50 rio newsyslog[1005]: logfile first created

I'm not sure why there are no logs: whether it because I did set the wrong rule or because I missed something enabling the logging...

Anyway, for some reason, the rule does not work. Do you have any ideas? Maybe I should give more info about something?
 
Since I decided to achieve this using ipfw, maybe this thread should now be moved into 'Firewalls' forum?
But AFAIK only moderators can move threads?
 
I tried this one:
Code:
# ipfw add fwd 192.168.1.1 tcp from any to any 25 via em0
# ipfw show
00100      0        0 allow ip from any to any via lo0
00200      0        0 deny ip from any to 127.0.0.0/8
00300      0        0 deny ip from 127.0.0.0/8 to any
00400      0        0 deny ip from any to ::1
00500      0        0 deny ip from ::1 to any
00600      2      232 allow ipv6-icmp from :: to ff02::/16
00700      0        0 allow ipv6-icmp from fe80::/10 to fe80::/10
00800      0        0 allow ipv6-icmp from fe80::/10 to ff02::/16
00900      0        0 allow ipv6-icmp from any to any icmp6types 1
01000      0        0 allow ipv6-icmp from any to any icmp6types 2,135,136
01200      0        0 fwd 192.168.1.1 tcp from any to any 25 via em0
65535      0        0 count ip from any to any not // orphaned dynamic states counter
65535 138722 45135352 allow ip from any to any

But still, when wireguard (VPN) is active, and I try to access port 25, the rule seems to be ignored:
Code:
# telnet smtp.gmail.com 25
Trying 142.250.102.108...
... and it hangs ...

I also enabled logging for ipfw:
Code:
options IPFIREWALL
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=5

/etc/rc.conf
Code:
firewall_enable="YES"
firewall_logging="YES"

But /var/log/security is empty:
Code:
Mar  8 10:31:50 rio newsyslog[1005]: logfile first created

I'm not sure why there are no logs: whether it because I did set the wrong rule or because I missed something enabling the logging...

Anyway, for some reason, the rule does not work. Do you have any ideas? Maybe I should give more info about something?
Alright, I found what I did wrong and managed some things to work.

I changed the rule to the following:
Code:
fwd 192.168.1.1 log tcp from me to any 25 via wg0

Now when VPN in on and I do
Code:
# telnet smtp.gmail.com 25
I got a log in /var/log/security:
Code:
ipfw: 1100 Forward to 192.168.1.1 TCP 10.66.66.2:18322 142.250.102.109:25
out via wg0
but the command is still hanging, i.e. I still can not reach 25 port when VPN is on. I'm not sure (my knowledge is very limited), but maybe this traffic still goes through wg0 interface and I need to somehow make it go through em0?..

I added this rule to see how 25 port packets go when I'm not connected to VPN:
Code:
allow log ip from any to any via em0
and when I do
Code:
# telnet smtp.gmail.com 25
without VPN, I got this log:
Code:
ipfw: 65534 Accept TCP 192.168.1.90:26261 192.178.155.109:25 out via em0

I'm not sure if I'm doing things correctly or not.
I would be happy to get a little help from someone experienced :)
 
try with the vpn on
nc -s 192.168.1.90 smtp.whatever.com 25 (replace 192.168.1.90 with the actual one if not correct)
see if that work
such a test wont confuse the gw/nat box
 
try with the vpn on
nc -s 192.168.1.90 smtp.whatever.com 25 (replace 192.168.1.90 with the actual one if not correct)
see if that work
such a test wont confuse the gw/nat box
Yes, that works!
Code:
# nc -s 192.168.1.90 smtp.gmail.com 25
220 smtp.gmail.com ESMTP 4fb4d7f45d1cf-64b912534f2sm23992231a12.15 - gsmtp

make sure that the box at 192.168.1.1 will nat / accept traffic from 10.x.y.z / your wg ip
Do I understand correctly that now (since my router sent a packet that has a source of 10.x.y.z) it will in reply receive packets that have a destination address of 10.x.y.z and I need to tell the router that traffic for port 25 that goes into 10.x.y.z should instead go to 192.168.1.90, port 25? I guess that will not work in case two machines in my local network (not only 192.168.1.90) will use such trick for forwarding mail traffic. Is it possible, when forwarding with ipfw, to actually change the source address of a packet, so that for router it will look like 192.168.1.90 sent it (not 10.x.y.z)? But maybe I'm again wrong :)
 
Back
Top