Hi Alexey,
you wrote:
> > + int want_rewrite = sysctl_ip_dynaddr & 4 || (sysctl_ip_dynaddr & 3 && sk->state == TCP_SYN_SENT);
>
> Did you read my comment there?
Yep. The only contra I can and want give is that it will not be randomly
but for a good reason. About the code around it I have not really an
idea -
but it works. I used what was allready there and just modified the logic
when to do it.
> Could you move all this under some CONFIG_* option?
Sure.
> Also, seems, this patch does not guarantee, that socket in established
> state is not mangled. Not good.
It's not a bug it's the feature. :-) If bit 2 (mask value 4) of
sysctl_ip_dynaddr is set this does mean all packets are rewritten this
does include these belonging to established connections. The goal is to
avoid sending out packets with an invalid source address in order to get
atleast an RST back.
Malware
--------------D367C91874E7504A4B58A8A7
Content-Type: text/plain; charset=us-ascii; name="linux-2.1.125-rst-2.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="linux-2.1.125-rst-2.diff"
--- linux/net/ipv4/tcp_ipv4.c.orig Sat Oct 17 17:32:15 1998
+++ linux/net/ipv4/tcp_ipv4.c Sun Oct 18 11:06:07 1998
@@ -44,6 +44,10 @@
* Andi Kleen: various fixes.
* Vitaly E. Lavrov : Transparent proxy revived after year coma.
* Andi Kleen : Fix new listen.
+ * Michael Mueller : Adapted RST-provoking patch for 2.0.xx
+ * by Erik Corry.
+ * Implemented work-around for asymetric
+ * routing and ip_dynaddr.
* Andi Kleen : Fix accept error reporting.
*/
@@ -67,7 +71,9 @@
extern int sysctl_tcp_window_scaling;
extern int sysctl_tcp_sack;
extern int sysctl_tcp_syncookies;
+#ifdef CONFIG_IP_DYNAMIC
extern int sysctl_ip_dynaddr;
+#endif
extern __u32 sysctl_wmem_max;
extern __u32 sysctl_rmem_max;
@@ -1707,11 +1713,16 @@
{
struct rtable *rt = (struct rtable *)sk->dst_cache;
__u32 new_saddr;
- int want_rewrite = sysctl_ip_dynaddr && sk->state == TCP_SYN_SENT;
+#if CONFIG_IP_DYNAMIC
+ struct device *dev;
+
+ int want_rewrite = sysctl_ip_dynaddr & 4 || (sysctl_ip_dynaddr & 3 && sk->state == TCP_SYN_SENT);
+#endif
if(rt == NULL)
return 0;
+#if CONFIG_IP_DYNAMIC
/* Force route checking if want_rewrite.
* The idea is good, the implementation is disguisting.
* Well, if I made bind on this socket, you cannot randomly ovewrite
@@ -1741,6 +1752,8 @@
dst_release(&new_rt->u.dst);
}
}
+#endif
+
if (rt->u.dst.obsolete) {
int err;
err = ip_route_output(&rt, rt->rt_dst, rt->rt_src, rt->key.tos|RTO_CONN, rt->key.oif);
@@ -1754,6 +1767,7 @@
return 0;
+#if CONFIG_IP_DYNAMIC
do_rewrite:
new_saddr = rt->rt_src;
@@ -1766,20 +1780,41 @@
return 0;
}
+ /* this should also not be happend! */
+ if (!new_saddr) {
+ printk(KERN_WARNING "tcp_v4_rebuild_header(): new source addrs"
+ "would be zero\n");
+ return 0;
+ }
+
if (new_saddr != sk->saddr) {
- if (sysctl_ip_dynaddr > 1) {
+ if (sysctl_ip_dynaddr & 2) {
printk(KERN_INFO "tcp_v4_rebuild_header(): shifting sk->saddr "
"from %d.%d.%d.%d to %d.%d.%d.%d\n",
NIPQUAD(sk->saddr),
NIPQUAD(new_saddr));
}
+ /* Check if there is not another interface having the
+ * new address. This should fix a problem with
+ * asymetric routing.
+ */
+ if ( sysctl_ip_dynaddr&8 && (dev=ip_dev_find(sk->saddr)) )
+ {
+ if (sysctl_ip_dynaddr & 2) {
+ printk(KERN_INFO "tcp_v4_rebuild_header(): shifting "
+ "skipped since device %s has matching addr\n", dev->name);
+ }
+ return 0;
+ }
+
sk->saddr = new_saddr;
sk->rcv_saddr = new_saddr;
tcp_v4_rehash(sk);
}
return 0;
+#endif
}
static struct sock * tcp_v4_get_sock(struct sk_buff *skb, struct tcphdr *th)
--- linux/net/ipv4/ip_masq.c.orig Sat Oct 17 17:32:14 1998
+++ linux/net/ipv4/ip_masq.c Sun Oct 18 10:58:08 1998
@@ -32,6 +32,10 @@
* Steven Clarke : IP_MASQ_S_xx state design
* Juan Jose Ciarlante : IP_MASQ_S state implementation
* Juan Jose Ciarlante : xx_get() clears timer, _put() inserts it
+ * Michael Mueller : Adapted RST-provoking patch for 2.0.xx
+ * by Erik Corry
+ * Implemented work-around for asymetric
+ * routing and ip_dynaddr
* Juan Jose Ciarlante : create /proc/net/ip_masq/
* Juan Jose Ciarlante : reworked checksums (save payload csum if possible)
* Juan Jose Ciarlante : added missing ip_fw_masquerade checksum
@@ -270,7 +274,9 @@
/*
* Dynamic address rewriting
*/
+#ifdef CONFIG_IP_DYNAMIC
extern int sysctl_ip_dynaddr;
+#endif
/*
* Lookup lock
@@ -977,6 +983,7 @@
struct iphdr *iph = skb->nh.iph;
union ip_masq_tphdr h;
struct ip_masq *ms;
+ struct device *dev;
int size;
/*
@@ -1050,27 +1057,42 @@
ms = ip_masq_out_get_iph(iph);
if (ms!=NULL) {
+#ifdef CONFIG_IP_DYNAMIC
/*
- * If sysctl !=0 and no pkt has been received yet
- * in this tunnel and routing iface address has changed...
+ * If sysctl & 3 and either no pkt has been received yet
+ * in this tunnel or sysctl & 4 and routing interface
+ * address has changed...
* "You are welcome, diald".
*/
- if ( sysctl_ip_dynaddr && ms->flags & IP_MASQ_F_NO_REPLY && maddr != ms->maddr) {
-
- if (sysctl_ip_dynaddr > 1) {
- IP_MASQ_INFO( "ip_fw_masquerade(): change masq.addr from %d.%d.%d.%d to %d.%d.%d.%d\n",
- NIPQUAD(ms->maddr),NIPQUAD(maddr));
- }
-
- write_lock(&__ip_masq_lock);
-
- ip_masq_unhash(ms);
- ms->maddr = maddr;
- ip_masq_hash(ms);
+ if ( (sysctl_ip_dynaddr & 3)
+ && (ms->flags & IP_MASQ_F_NO_REPLY || sysctl_ip_dynaddr & 4 )
+ && (maddr != ms->maddr)
+ ) {
+ if ( sysctl_ip_dynaddr&8 && (dev=ip_dev_find(maddr)) )
+ {
+ if ( sysctl_ip_dynaddr & 2 )
+ {
+ IP_MASQ_INFO( "ip_fw_masquerade(): skipped changing masq.addr since "
+ "device %s does match %d.%d.%d.%d\n", dev->name, NIPQUAD(maddr));
+ }
+ } else {
+ if ( sysctl_ip_dynaddr & 2 )
+ {
+ IP_MASQ_INFO( "ip_fw_masquerade(): change masq.addr from "
+ "%d.%d.%d.%d to %d.%d.%d.%d\n", NIPQUAD(ms->maddr),NIPQUAD(maddr));
+ }
+
+ write_lock(&__ip_masq_lock);
+
+ ip_masq_unhash(ms);
+ ms->maddr = maddr;
+ ip_masq_hash(ms);
- write_unlock(&__ip_masq_lock);
+ write_unlock(&__ip_masq_lock);
+ }
}
-
+
+#endif
/*
* Set sport if not defined yet (e.g. ftp PASV). Because
* masq entries are hashed on sport, unhash with old value
@@ -1224,7 +1246,9 @@
struct iphdr *ciph; /* The ip header contained within the ICMP */
__u16 *pptr; /* port numbers from TCP/UDP contained header */
struct ip_masq *ms;
+ struct device *dev;
unsigned short len = ntohs(iph->tot_len) - (iph->ihl * 4);
+
IP_MASQ_DEBUG(2, "Incoming forward ICMP (%d,%d) %lX -> %lX\n",
icmph->type, ntohs(icmp_id(icmph)),
@@ -1257,28 +1281,44 @@
return (-1);
IP_MASQ_DEBUG(1, "Created new icmp entry\n");
}
+
+#ifdef CONFIG_IP_DYNAMIC
/* Rewrite source address */
/*
- * If sysctl !=0 and no pkt has been received yet
- * in this tunnel and routing iface address has changed...
+ * If sysctl & 3 and either no pkt has been received yet
+ * in this tunnel or sysctl & 4 and routing interface
+ * address has changed...
* "You are welcome, diald".
*/
- if ( sysctl_ip_dynaddr && ms->flags & IP_MASQ_F_NO_REPLY && maddr != ms->maddr) {
-
- if (sysctl_ip_dynaddr > 1) {
- IP_MASQ_INFO( "ip_fw_masq_icmp(): change masq.addr %d.%d.%d.%d to %d.%d.%d.%d",
- NIPQUAD(ms->maddr), NIPQUAD(maddr));
- }
+ if ( (sysctl_ip_dynaddr & 3 )
+ && (ms->flags & IP_MASQ_F_NO_REPLY || sysctl_ip_dynaddr & 4)
+ && maddr != ms->maddr
+ ) {
+ if ( sysctl_ip_dynaddr&8 && (dev=ip_dev_find(maddr)) )
+ {
+ if ( sysctl_ip_dynaddr & 2 )
+ {
+ IP_MASQ_INFO( "ip_fw_masq_icmp(): skipped changing masq.addr since "
+ "device %s does match %d.%d.%d.%d\n", dev->name, NIPQUAD(maddr));
+ }
+ } else {
+ if ( sysctl_ip_dynaddr & 2 )
+ {
+ IP_MASQ_INFO( "ip_fw_masq_icmp(): change masq.addr from "
+ "%d.%d.%d.%d to %d.%d.%d.%d\n", NIPQUAD(ms->maddr),NIPQUAD(maddr));
+ }
- write_lock(&__ip_masq_lock);
+ write_lock(&__ip_masq_lock);
- ip_masq_unhash(ms);
- ms->maddr = maddr;
- ip_masq_hash(ms);
+ ip_masq_unhash(ms);
+ ms->maddr = maddr;
+ ip_masq_hash(ms);
- write_unlock(&__ip_masq_lock);
+ write_unlock(&__ip_masq_lock);
+ }
}
+#endif
iph->saddr = ms->maddr;
ip_send_check(iph);
--- linux/net/ipv4/ip_output.c.orig Sat Oct 17 17:32:14 1998
+++ linux/net/ipv4/ip_output.c Sun Oct 18 10:57:06 1998
@@ -79,7 +79,9 @@
* Shall we try to damage output packets if routing dev changes?
*/
+#ifdef CONFIG_IP_DYNAMIC
int sysctl_ip_dynaddr = 0;
+#endif
int ip_id_count = 0;
--- linux/net/ipv4/sysctl_net_ipv4.c.orig Sat Oct 17 17:32:15 1998
+++ linux/net/ipv4/sysctl_net_ipv4.c Sun Oct 18 10:56:53 1998
@@ -37,8 +37,10 @@
extern int sysctl_ipfrag_high_thresh;
extern int sysctl_ipfrag_time;
+#ifdef CONFIG_IP_DYNAMIC
/* From ip_output.c */
extern int sysctl_ip_dynaddr;
+#endif
/* From ip_masq.c */
extern int sysctl_ip_masq_debug;
@@ -125,8 +127,10 @@
&sysctl_ipfrag_high_thresh, sizeof(int), 0644, NULL, &proc_dointvec},
{NET_IPV4_IPFRAG_LOW_THRESH, "ipfrag_low_thresh",
&sysctl_ipfrag_low_thresh, sizeof(int), 0644, NULL, &proc_dointvec},
+#ifdef CONFIG_IP_DYNAMIC
{NET_IPV4_DYNADDR, "ip_dynaddr",
&sysctl_ip_dynaddr, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
#ifdef CONFIG_IP_MASQUERADE
{NET_IPV4_IP_MASQ_DEBUG, "ip_masq_debug",
&sysctl_ip_masq_debug, sizeof(int), 0644, NULL, &proc_dointvec},
--- linux/net/ipv4/Config.in.orig Sat Oct 17 17:32:13 1998
+++ linux/net/ipv4/Config.in Sun Oct 18 11:03:15 1998
@@ -35,6 +35,7 @@
bool 'IP: always defragment' CONFIG_IP_ALWAYS_DEFRAG
fi
fi
+bool 'IP: dynamic address hack' CONFIG_IP_DYNAMIC
if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
bool 'IP: masquerading' CONFIG_IP_MASQUERADE
if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then
--- linux/Documentation/networking/ip_dynaddr.txt.orig Sat May 9 23:25:38 1998
+++ linux/Documentation/networking/ip_dynaddr.txt Sun Oct 18 11:08:29 1998
@@ -1,10 +1,14 @@
-IP dynamic address hack-port v0.03
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+IP dynamic address hack-port v0.03-rst2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+** You need to enable the option CONFIG_IP_DYNAMIC during kernel compilation
+** in order to have this feature included.
+
This stuff allows diald ONESHOT connections to get established by
dynamically changing packet source address (and socket's if local procs).
It is implemented for TCP diald-box connections(1) and IP_MASQuerading(2).
-If enabled[*] and forwarding interface has changed:
+If enabled[*] and forwarding interface address has changed:
1) Socket (and packet) source address is rewritten ON RETRANSMISSIONS
while in SYN_SENT state (diald-box processes).
2) Out-bounded MASQueraded source address changes ON OUTPUT (when
@@ -16,14 +20,51 @@
going up. So, the *same* (local AND masqueraded) connections requests that
bring the link up will be able to get established.
-[*] At boot, by default no address rewriting is attempted.
- To enable:
+If you enable the RST-provoking mode, then the source address will
+be changed, even if the socket is established. This means we send
+an incorrect packet out, which causes the remote host to kill our
+socket. This is the desired behaviour, because such a socket is
+doomed anyway, and the earlier it dies, the better. This prevents
+the dial-on-demand connection from being kept up by a dead connection,
+and tells the application that the connection was lost.
+
+With the RST-provoking mode enabled it happens packets with the address
+of another interface as source are rewritten and get a new source address
+this way. If you have asymetric routing and the other interfaces have
+static addresses enabling the work-around might[**] help you.
+
+[*] At boot, by default no address rewriting is attempted.
+[**] This code is currently totaly untested.
+
+The values for the ip_dynaddr sysctl are:
+
+ 1: To enable:
+ 2: To enable verbosity:
+ 4: To enable RST-provoking:
+ 8: To enable asymetric routing work-around
+
+Flags can be combined by adding them. Common settings
+would be:
+
+ To switch off special handling of dynamic addresses (default)
+ # echo 0 > /proc/sys/net/ipv4/ip_dynaddr
+ To enable rewriting in quiet mode:
# echo 1 > /proc/sys/net/ipv4/ip_dynaddr
- To enable verbose mode:
+ To enable rewriting in verbose mode:
+ # echo 3 > /proc/sys/net/ipv4/ip_dynaddr
+ (for backwards compatibility you can also use)
# echo 2 > /proc/sys/net/ipv4/ip_dynaddr
- To disable (default)
- # echo 0 > /proc/sys/net/ipv4/ip_dynaddr
+ To enable quiet RST-provoking mode:
+ # echo 5 > /proc/sys/net/ipv4/ip_dynaddr
+ To enable verbose RST-provoking mode:
+ # echo 7 > /proc/sys/net/ipv4/ip_dynaddr
+ To enable quiet RST-provoking mode with asymetric routing work-around:
+ # echo 13 > /proc/sys/net/ipv4/ip_dynaddr
+ To enable verbose RST-provoking mode with asymetric routing work-around:
+ # echo 15 > /proc/sys/net/ipv4/ip_dynaddr
Enjoy!
-- Juanjo <jjciarla@raiz.uncu.edu.ar>
+(with RST-provoking mode by Erik Corry <erik@arbat.com> and asymetric routing
+ work-around by Michael Mueller <Michael.Mueller4@post.rwth-aachen.de>)
--------------D367C91874E7504A4B58A8A7--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/