Date: Mon, 28 Apr 2008 06:01:26 -0500 From: "David Todd" <mobilepolice@gmail.com> To: freebsd-net@freebsd.org Cc: seki@fexx.org Subject: custom modifications to libalias for detailed translation information (patch included) Message-ID: <b91012310804280401g3a71e577k908546972a96e2c4@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] Gentlemen, I've expanded upon the work of Masahiro Sekiguchi <seki@fexx.org>'s patch for libalias located at: http://www.fexx.org/ybb/alias_db.c.diff.txt This alias_db.c diff modified libalias in a way to replace the original /var/log/alias.log file with one that reported running statistics in a format like such: + udp 219.63.255.49:1024 211.5.1.219:53 219.63.255.49:1024 *:* (0x8060100) + udp 219.63.255.49:1024 165.76.0.98:53 219.63.255.49:1024 *:* (0x8060180) + udp 219.63.255.49:1024 165.76.4.2:53 219.63.255.49:1024 *:* (0x8060200) + udp 219.63.255.49:1024 211.5.1.217:53 219.63.255.49:1024 *:* (0x8060280) + tcp 192.168.1.188:1346 210.142.46.154:80 219.63.255.49:1346 *:* (0x8060300) + udp 219.63.255.49:1024 210.141.108.194:53 219.63.255.49:1024 *:* (0x8060400) + udp 219.63.255.49:1024 210.239.166.194:53 219.63.255.49:1024 *:* (0x8060480) Obviously this patch was built for a much older version of libalias; circa 2003. I recently attempted to convert his work, modify it (relatively heavily) for my own uses and what I think makes a bit better sense; after a few weeks of testing and repeated modifications I'm ready to give it to whomever thinks they could make use of it. The highlights of my changes: * alias.log becomes 'alias' under /var/log; it is no longer a massive running list of connection #'s per protocol, but a one-line file updated every 20 seconds showing current protocol #'s. * alias.details is a new log under /var/log which provides interesting information on all of the active translated connections in a format that looks like this: total: 485 time: 1209374774 last_chg exp_t T- protocol source addr:port dest addr:port alias addr:port proxy addr:port 1209374770 00060 -00056 udp 192.0.21.10:8080 78.109.177.139:61878 *:8080 *:* 1209374733 00010 00000 tcp DIS:DIS 192.0.21.10:3276 209.85.133.18:80 68.52.101.103:3276 *:* 1209374635 00060 00000 icmp 68.52.101.103:1 67.15.240.42:256 68.52.101.103:1 *:* 1209374566 00300 -00092 tcp EST:DWN 68.52.101.103:11225 69.60.111.193:39357 68.52.101.103:11225 *:* 1209374747 00010 00000 tcp DIS:DIS 192.0.21.10:3261 209.85.133.19:80 68.52.101.103:3261 *:* 1209374078 00300 00000 tcp PERMLNK 192.0.21.10:5580 *:* *:5580 *:* (if your email client supports tabbed text properly the format of the log looks much cleaner) * modified TCP_EXPIRE_CONNECTED from 24 hours to 1 hour (did this for debugging purposes, it can be set to whatever standard there is) I ran into this bug: BUG: when a TCP connection is dropped locally (behind the nat) or remotely, sometimes libalias/natd does not mark the translated TCP connection as down/disconnected/dead. The connection will remain in the translation tables until libalias/natd is reloaded. This could be just a problem with natd but I do not have the proper tools or environment to figure out exactly where the problem is coming from, leading to this: * modification: when idelta > lnk->expire_time and LINK_TCP in IncrementalCleanup(), SetStateIn/Out ALIAS_TCP_NOT_CONNECTED, reset lnk->timestamp to current la->timeStamp and set lnk->expire_time to TCP_EXPIRE_SINGLEDEAD; on the pass after next of the IncrementalCleanup() function we'll come across the same translation entry, if it hasn't changed we'll expire it. The issue here is that after a period of time I had 1500+ TCP connections in my translation tables all showing a "time to expire" of 0 seconds (out of 86400); and no activity on the network to warrant such connections. In normal TCP connections when a packet is processed for a translation entry lnk->timestamp is updated, so idelta will never exceed lnk->expire_time as long as the link is actually communicating packets; I feel like this was a safe compromise and it has not negatively affected my computing habits yet - but granted, I am neither a power user nor everyone else, so this solution/hack/crapshoot is open for interpritation. It's my experience with most commercial firewalls will drop inactive links after 15 min-1hr, etc. I've abused calls to AliasLog with this patch. I'm still a relative novice to C programming and memory management, so the last thing I wanted to deal with was mallocing crap and working with string buffers/etc and create all kinds of havoc. I'm not sure what sort of impact this has on the performance of the program; from my experience I've had 6000+ established UDP and TCP connections going at once (with about 800KB/s load) and my 1Ghz Celeron machine has seen about 30% load; it's important to note that libalias was rewriting the alias.details log every 75 state changes, instead of every 20 seconds like it does now; so it's likely the load will be significantly lower. I know there's been some recent changes to alias_db.c in the CVS which I did not have at the time I started making these changes, so I tried to keep what I've changed to a minimum in order to insure an easy patching process if any of you decide to implement this. Thanks to Masahiro Sekiguchi for his original work as an inspiration for me to do this; I don't know if anyone else uses ipfw/natd anymore (I know I do!) but if they do, they might find this useful. Any comments are appreciated. Regards, David Todd [-- Attachment #2 --] --- alias_db.c.orig 2008-04-08 18:31:15.000000000 -0500 +++ alias_db.c 2008-04-28 04:14:03.000000000 -0500 @@ -159,6 +159,7 @@ #include <sys/socket.h> #include <netinet/tcp.h> +#include <arpa/inet.h> #ifdef _KERNEL #include <netinet/libalias/alias.h> @@ -210,7 +211,7 @@ /* When the link is up */ #ifndef TCP_EXPIRE_CONNECTED -#define TCP_EXPIRE_CONNECTED 86400 +#define TCP_EXPIRE_CONNECTED 3600 // old: 86400 (24 hours) ?! #endif @@ -306,7 +307,7 @@ #define LINK_ADDR (IPPROTO_MAX + 3) #define LINK_PPTP (IPPROTO_MAX + 4) - int flags; /* indicates special characteristics */ + int flags; /* indicates special recharacteristics */ int pflags; /* protocol-specific flags */ /* flag bits */ @@ -404,6 +405,10 @@ #endif /* Log file control */ +static void ShowLinkType(struct alias_link *, struct libalias *); +static void ShowAddrAndPort(struct in_addr, u_short, struct libalias *); +static void ShowAliasDetails(struct libalias *); + static void ShowAliasStats(struct libalias *); static int InitPacketAliasLog(struct libalias *); static void UninitPacketAliasLog(struct libalias *); @@ -460,7 +465,7 @@ AliasLog(char *str, const char *format, ...) { va_list ap; - + va_start(ap, format); vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap); va_end(ap); @@ -470,7 +475,7 @@ AliasLog(FILE *stream, const char *format, ...) { va_list ap; - + va_start(ap, format); vfprintf(stream, format, ap); va_end(ap); @@ -478,13 +483,148 @@ } #endif + +/* + * Function: ShowLinkType() + * Return : nothing + * Side Eff: call AliasLog with results of the link type, if link_type = LINK_TCP + * call GetStateIn/Out(lnk) to provide more details about the current TCP state. + * Calls : AliasLog, GetStateIn, GetStateOut +*/ +static void +ShowLinkType(struct alias_link *lnk, struct libalias *la) +{ +#ifndef _KERNEL + + switch (lnk->link_type) { + case LINK_ICMP: AliasLog(la->logDetails, "%-11s ", "icmp"); break; + case LINK_TCP: + AliasLog(la->logDetails, "tcp "); + if (lnk->flags & LINK_PERMANENT) { + AliasLog(la->logDetails, "PERMLNK "); + } else { + switch (GetStateIn(lnk)) { + case ALIAS_TCP_STATE_CONNECTED: AliasLog(la->logDetails, "EST:"); break; + case ALIAS_TCP_STATE_DISCONNECTED: AliasLog(la->logDetails, "DIS:"); break; + case ALIAS_TCP_STATE_NOT_CONNECTED: AliasLog(la->logDetails, "DWN:"); break; + default: AliasLog(la->logDetails, "UNK:"); break; + } + switch (GetStateOut(lnk)) { + case ALIAS_TCP_STATE_CONNECTED: AliasLog(la->logDetails, "EST "); break; + case ALIAS_TCP_STATE_DISCONNECTED: AliasLog(la->logDetails, "DIS "); break; + case ALIAS_TCP_STATE_NOT_CONNECTED: AliasLog(la->logDetails, "DWN "); break; + default: AliasLog(la->logDetails, "UNK "); break; + } + } + break; + case LINK_UDP: AliasLog(la->logDetails, "%-11s ", "udp"); break; + case LINK_FRAGMENT_ID: AliasLog(la->logDetails, "%-11s ", "[frag_id]"); break; + case LINK_FRAGMENT_PTR: AliasLog(la->logDetails, "%-11s ", "[frag_ptr]"); break; + case LINK_ADDR: AliasLog(la->logDetails, "%-11s ", "[addr]"); break; + case LINK_PPTP: AliasLog(la->logDetails, "%-11s ", "[pptp]"); break; + default: AliasLog(la->logDetails, "[%-9d] ", lnk->link_type); break; + } +#endif +} + +/* + * Function: ShowAddrAndPort() + * Return : nothing + * Side Eff: simple expression for output of IP address and port or "*:*" + * to logDetails log file. Implemented to prevent code repeition. + * Calls : AliasLog +*/ +static void +ShowAddrAndPort(struct in_addr addr, u_short port, struct libalias *la) +{ +#ifndef _KERNEL + if (la->logDetails) { + AliasLog(la->logDetails, + port == 0 ? "%15s:* " : "%15s:%-6u ", + addr.s_addr == INADDR_ANY ? "*" : inet_ntoa(addr), + ntohs(port)); + } +#endif +} + + +/* + * Function: ShowAliasDetails(struct libalias *) + * Return : nothing + * Side Eff: Walk our list of links every 20 seconds, abusively call AliasLog + * to output details of all of our links to /var/log/alias.details; this function + * will not write to the output file in kld-mode. + * Calls : AliasLog (abusively), ShowAddrAndPort, ShowLinkType, +*/ +static void +ShowAliasDetails(struct libalias *la) +{ + + if ((la->lastDetailsTime + 20) <= la->timeStamp) { // update every 20 seconds. + la->lastDetailsTime = la->timeStamp; + } else { + return; + } + + ShowAliasStats(la); + +#ifndef _KERNEL + if (la->logDetails) { + + struct alias_link *lk; + int i; + + freopen(NULL, "w", la->logDetails); // zero our stream and reopen. + + LIBALIAS_LOCK_ASSERT(la); + + AliasLog(la->logDetails, // write header to stream + "total: %d\n" \ + "time: %d\n" \ + "last_chg exp_t T- protocol source addr:port dest addr:port alias addr:port proxy addr:port\n", + la->icmpLinkCount + la->udpLinkCount + la->tcpLinkCount + la->pptpLinkCount + + la->protoLinkCount + la->fragmentIdLinkCount + la->fragmentPtrLinkCount, + la->timeStamp); + + for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { // probably should time this function to measure impact. + lk = LIST_FIRST(&la->linkTableOut[i]); + while (lk != NULL) { + struct alias_link *lk_next; + lk_next = LIST_NEXT(lk, list_out); + + AliasLog(la->logDetails, "%10d %5.5d %6.5d ", + lk->timestamp, // time of last packet through connection + lk->expire_time, // timeout period after last packet + (la->timeStamp - lk->expire_time) > lk->timestamp ? 0 : la->timeStamp - (lk->timestamp + lk->expire_time)); + // don't need to see positive values, easier to look through the log for "00000" + + ShowLinkType(lk, la); + ShowAddrAndPort(lk->src_addr, lk->src_port, la); // source (internal address) + ShowAddrAndPort(lk->dst_addr, lk->dst_port, la); // dest (external address) + ShowAddrAndPort(lk->alias_addr, lk->alias_port, la); // alias (our public address) + ShowAddrAndPort(lk->proxy_addr, lk->proxy_port, la); // proxy ? + AliasLog(la->logDetails, "\n"); + + lk = lk_next; + } + } + } +#endif +} + + static void ShowAliasStats(struct libalias *la) { LIBALIAS_LOCK_ASSERT(la); -/* Used for debugging */ + if (la->logDesc) { + +#ifndef _KERNEL + freopen(NULL, "w", la->logDesc); // zero our stream and start from the top +#endif + int tot = la->icmpLinkCount + la->udpLinkCount + la->tcpLinkCount + la->pptpLinkCount + la->protoLinkCount + la->fragmentIdLinkCount + @@ -814,17 +954,15 @@ CleanupAliasData(struct libalias *la) { struct alias_link *lnk; - int i, icount; + int i; LIBALIAS_LOCK_ASSERT(la); - icount = 0; for (i = 0; i < LINK_TABLE_OUT_SIZE; i++) { lnk = LIST_FIRST(&la->linkTableOut[i]); while (lnk != NULL) { struct alias_link *link_next; link_next = LIST_NEXT(lnk, list_out); - icount++; DeleteLink(lnk); lnk = link_next; } @@ -837,11 +975,9 @@ static void IncrementalCleanup(struct libalias *la) { - int icount; struct alias_link *lnk; LIBALIAS_LOCK_ASSERT(la); - icount = 0; lnk = LIST_FIRST(&la->linkTableOut[la->cleanupIndex++]); while (lnk != NULL) { int idelta; @@ -852,21 +988,23 @@ switch (lnk->link_type) { case LINK_TCP: if (idelta > lnk->expire_time) { - struct tcp_dat *tcp_aux; - - tcp_aux = lnk->data.tcp; - if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED - || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED) { + if (GetStateIn(lnk) != ALIAS_TCP_STATE_CONNECTED + || GetStateOut(lnk) != ALIAS_TCP_STATE_CONNECTED) { DeleteLink(lnk); - icount++; + } else { + /* expire_time is up, set the link as disconnected, on the pass + * 120s from now if it's still disconnected then we'll dump the link. + */ + SetStateIn(lnk, ALIAS_TCP_STATE_NOT_CONNECTED); + SetStateOut(lnk, ALIAS_TCP_STATE_NOT_CONNECTED); + lnk->expire_time = TCP_EXPIRE_SINGLEDEAD; + lnk->timestamp = la->timeStamp; } } break; default: - if (idelta > lnk->expire_time) { + if (idelta > lnk->expire_time) DeleteLink(lnk); - icount++; - } break; } lnk = link_next; @@ -943,13 +1081,15 @@ break; } -/* Free memory */ - free(lnk); /* Write statistics, if logging enabled */ if (la->packetAliasMode & PKT_ALIAS_LOG) { - ShowAliasStats(la); + ShowAliasDetails(la); } + +/* Free memory */ + free(lnk); + } @@ -1089,7 +1229,7 @@ #endif } if (la->packetAliasMode & PKT_ALIAS_LOG) { - ShowAliasStats(la); + ShowAliasDetails(la); } return (lnk); } @@ -2262,8 +2402,15 @@ if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE))) ; #else - if ((la->logDesc = fopen("/var/log/alias.log", "w"))) + if ((la->logDesc = fopen("/var/log/alias", "w"))) fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"); + else + return (ENOMEM); + + if ((la->logDetails = fopen("/var/log/alias.details", "w"))) { + fprintf(la->logDetails, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n"); + la->lastDetailsTime = la->timeStamp; + } #endif else return (ENOMEM); /* log initialization failed */ @@ -2284,6 +2431,10 @@ free(la->logDesc); #else fclose(la->logDesc); + if (la->logDetails) { + fclose(la->logDetails); + la->logDetails = NULL; + } #endif la->logDesc = NULL; } --- alias_local.h.orig 2008-04-09 17:46:25.000000000 -0500 +++ alias_local.h 2008-04-28 02:53:26.000000000 -0500 @@ -100,6 +100,8 @@ int fragmentPtrLinkCount; int sockCount; + int lastDetailsTime; + int cleanupIndex; /* Index to chain of link table */ /* being inspected for old links */ @@ -120,6 +122,7 @@ char *logDesc; #else FILE *logDesc; + FILE *logDetails; #endif /* statistics monitoring */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?b91012310804280401g3a71e577k908546972a96e2c4>
