On Wed, Dec 04, 2002 at 11:37:17PM -0500, Ilya wrote:
> default router is Cable. IPNAT works fine, no problem. but any incoming
> traffic to services on DSL interface is being replied to from cable
> interface. Therefore rendering DSL useless.
> Have anyone been able to solve this problem? Or has any suggestions to it?
Yes you can solve it with a patch and a rule like this:
pass in on <dsl-if> to <dls-if>:<router> <your spec> keep state
e.g.:
pass in on ep0 to ep0:1.2.3.4 from any to 10.0.0.1 port 80 keep state
Normally ipfilter does not remember the interface a packet came in from,
and the abover rule is disallowed.
I made the attached patch a long time ago and probably it is not 100% correct.
But it works for me. Use at your own risk and be advised I have
absolutelyu no time right now to support it.
-Guido
--- ip_fil.c.orig Sat Aug 31 18:24:52 2002
+++ ip_fil.c Thu Dec 5 08:45:27 2002
@@ -1605,16 +1605,67 @@
ifp = fin->fin_ifp;
/*
+ * There are multiple ways to get here
+ * 1) via send_ip as a response to an incoming packet, the fdp == NULL
+ * 2) to <if>, then fdp is outgoing interface, fr != NULL
+ * 3) dupto <if>, then fdp is outgoing interface, fr != NULL
+ * 4) fastroute, then fdp = NULL
+ */
+ /*
* In case we're here due to "to <if>" being used with "keep state",
* check that we're going in the correct direction.
*/
- if ((fr != NULL) && (fin->fin_rev != 0)) {
- if ((ifp != NULL) && (fdp == &fr->fr_tif))
- return 0;
+ if ((fr != NULL) && (fdp != NULL) &&
+ ((ip->ip_dst.s_addr & fr->fr_smsk.s_addr) == fr->fr_src.s_addr) &&
+ ((ip->ip_src.s_addr & fr->fr_dmsk.s_addr) == fr->fr_dst.s_addr)) {
+ /* We get here when we match a filterrule reversed (i.e.
+ * a return packet
+ */
+ /* kludge to get on "on ed0 to ed0:1.2.3.4" working */
+ if (fr->fr_ifa == fdp->fd_ifp) {
+ /* if outgoing interface equals rule interface */
+ ifp = fdp->fd_ifp;
+ /* send it to ip address in to: rule if available */
+ if (fdp->fd_ip.s_addr != 0) {
+ dst->sin_addr = fdp->fd_ip;
+ }
+ } else {
+ /* if outgoing interface doesn't match rule interface */
+ ifp = fr->fr_ifa;
+ }
+ } else if ((fr != NULL) && (fdp != NULL)) {
+ /* kludge to get on "on ed0 to ed0:1.2.3.4" working */
+ if (fr->fr_ifa == fdp->fd_ifp) {
+ ifp = NULL;
+ } else {
+ ifp = fdp->fd_ifp;
+ if (fdp->fd_ip.s_addr != 0) {
+ dst->sin_addr = fdp->fd_ip;
+ }
+ }
} else if (fdp != NULL) {
- if (fdp->fd_ip.s_addr != 0)
+ if (fdp->fd_ip.s_addr != 0) {
dst->sin_addr = fdp->fd_ip;
+ }
+ } else {
+ /* fdp equals NULL */
+ /* We came here via return something */
+ if ((fr != NULL) && fr->fr_tif.fd_ifp &&
+ (fr->fr_tif.fd_ifp != (void *)-1) &&
+ fr->fr_tif.fd_ip.s_addr) {
+ /* This means we have a rule like:
+ * block return-rst to <if>:ip address
+ */
+ dst->sin_addr = fr->fr_tif.fd_ip;
+ }
}
+ /*
+ * An incoming packet from the interface we are sending packets to.
+ * We don't really want to route it.
+ */
+ if ((fin->fin_out == 0) && (fdp == &fr->fr_tif) &&
+ (ifp == fin->fin_ifp))
+ return 0;
# if BSD >= 199306
dst->sin_len = sizeof(*dst);
@@ -1634,12 +1685,14 @@
ROUTE_UNLOCK();
#endif
+#if 0
if (!ifp) {
if (!fr || !(fr->fr_flags & FR_FASTROUTE)) {
error = -2;
goto bad;
}
}
+#endif
if ((ifp == NULL) && (ro->ro_rt != NULL))
ifp = ro->ro_rt->rt_ifp;
@@ -1681,6 +1734,9 @@
fin->fin_ifp = sifp;
} else
ip->ip_sum = 0;
+/*XXX*/
+ ip->ip_sum = 0;
+
/*
* If small enough for interface, can just send directly.
*/