lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Thu, 2 Aug 2007 09:19:06 +0300 (EEST) From: john@...een.lv To: netdev@...r.kernel.org Subject: strange tcp behavior 1186035057.207629 127.0.0.1 -> 127.0.0.1 TCP 50000 > smtp [SYN] Seq=0 Len=0 1186035057.207632 127.0.0.1 -> 127.0.0.1 TCP smtp > 50000 [SYN, ACK] Seq=0 Ack=1 Win=32792 Len=0 MSS=16396 1186035057.207666 127.0.0.1 -> 127.0.0.1 TCP 50000 > smtp [ACK] Seq=1 Ack=1 Win=1500 Len=0 1186035057.207699 127.0.0.1 -> 127.0.0.1 SMTP Command: EHLO localhost 1186035057.207718 127.0.0.1 -> 127.0.0.1 TCP smtp > 50000 [ACK] Seq=1 Ack=17 Win=32792 Len=0 1186035057.207736 127.0.0.1 -> 127.0.0.1 TCP 50000 > smtp [RST] Seq=17 Len=0 1186035057.223934 127.0.0.1 -> 127.0.0.1 TCP 33787 > 50000 [RST, ACK] Seq=0 Ack=0 Win=32792 Len=0 Can someone please comment as to why, tcp stack sends rst packet from the wrong source port in this situation. This is the same problem that was described in my first two posts, witch unfortunately nobody seemed to notice. Here is source code witch can reproduce the behavior described, the client side code is a complete mess but with a little bit it works. Server: #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <poll.h> #include <fcntl.h> void main(void) { int ms; int ss; struct sockaddr_in sa; char *str = "HELLO FRIEND"; struct pollfd fd; int flags; ms = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); flags = fcntl(ms, F_GETFL, 0); fcntl(ms, F_SETFL, flags | O_NONBLOCK); memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(25); bind(ms, (struct sockaddr *) &sa, sizeof(sa)); listen(ms, 0); fd.fd = ms; fd.events = POLLIN; while(poll(&fd, 1, -1)) { ss = accept(ms, NULL, NULL); usleep(10000); send(ss, str, strlen(str), MSG_NOSIGNAL); close(ss); memset(&fd, 0, sizeof(fd)); fd.fd = ms; fd.events = POLLIN; } } Client: #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <linux/if_ether.h> //#include <arpa/inet.h> //#include <linux/if_ether.h> struct sockaddr_in localaddr; struct sockaddr_in remoteaddr; struct sockaddr rawaddr; int sdl, sdr; struct tcphdr header; struct pheader_t { uint32_t saddr; uint32_t daddr; uint8_t r; uint8_t protocol; uint16_t length; }; struct pheader_t pheader; unsigned short tbuf[2048]; unsigned char buf[2048]; char *msg = "EHLO localhost\r\n"; unsigned char *p; char *src_addr = "127.0.0.1"; char *dst_addr = "127.0.0.1"; unsigned short sprt = 50000; unsigned short dprt = 25; struct timeval tv; unsigned seq, ack_seq; int data; void mysend(void) { int i, sum; int len; if(data) { len = strlen(msg); memcpy((char *) tbuf + sizeof(pheader) + sizeof(header), msg, len); } else len = 0; bzero(&pheader, sizeof(pheader)); pheader.saddr = (in_addr_t) inet_addr(src_addr); pheader.daddr = (in_addr_t) inet_addr(dst_addr); pheader.protocol = 6; pheader.length = htons(sizeof(header) + len); memcpy(tbuf, &pheader, sizeof(pheader)); memcpy((char *) tbuf + sizeof(pheader), &header, sizeof(header)); sum = 0; for(i = 0; i < (sizeof(pheader) + sizeof(header)) / 2 + len / 2; i++) { sum += tbuf[i]; sum = (sum & 0x0000ffff) + (sum >> 16); } header.check = ~sum; memcpy((char *) tbuf + sizeof(pheader), &header, sizeof(header)); sendto(sdr, (char *) tbuf + sizeof(pheader), sizeof(header) + len, 0, (struct sockaddr *) &remoteaddr, sizeof(remoteaddr)); } void main(void) { gettimeofday(&tv, NULL); srand(tv.tv_sec & tv.tv_usec); remoteaddr.sin_family = AF_INET; remoteaddr.sin_addr.s_addr = (in_addr_t) inet_addr(dst_addr); sdl = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); strcpy(rawaddr.sa_data, "lo"); bind(sdl, (struct sockaddr *) &rawaddr, sizeof(rawaddr)); sdr = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); bzero(&header, sizeof(header)); header.source = htons(sprt); header.dest = htons(dprt); seq = rand(); ack_seq = 0; header.seq = htonl(seq); header.ack_seq = htonl(ack_seq); header.doff = sizeof(header) / 4; header.syn = 1; header.window = htons(1500); mysend(); while(1) { recvfrom(sdl, buf, sizeof(buf), 0, NULL, NULL); // p = buf + (*buf & 0x0f) * 4; p = (buf + 14) + (*(buf + 14) & 0x0f) * 4; if(ntohs(((struct tcphdr *)p)->source) == dprt && ntohs(((struct tcphdr *)p)->dest) == sprt && ((struct tcphdr *)p)->syn == 1 && ((struct tcphdr *)p)->ack == 1) break; } bzero(&header, sizeof(header)); header.source = htons(sprt); header.dest = htons(dprt); seq = ntohl(((struct tcphdr *)p)->ack_seq); ack_seq = ntohl(((struct tcphdr *)p)->seq) + 1; header.seq = htonl(seq); header.ack_seq = htonl(ack_seq); header.doff = sizeof(header) / 4; header.ack = 1; header.window = htons(1500); mysend(); bzero(&header, sizeof(header)); header.source = htons(sprt); header.dest = htons(dprt); header.seq = htonl(seq); header.ack_seq = htonl(ack_seq); header.doff = sizeof(header) / 4; header.ack = 1; header.psh = 1; header.window = htons(1500); data = 1; mysend(); data = 0; // usleep(300); bzero(&header, sizeof(header)); header.source = htons(sprt); header.dest = htons(dprt); seq += strlen(msg); header.seq = htonl(seq); header.ack_seq = htonl(ack_seq); header.doff = sizeof(header) / 4; header.rst = 1; header.window = htons(1500); mysend(); } I traced this behavior way back to 2.4.0-test9-pre3 kernel. - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists