|
ru.unix.bsd- RU.UNIX.BSD ------------------------------------------------------------------ From : Vadim Goncharov 2:5020/400 04 Mar 2008 12:00:53 To : Alex Semenyaka Subject : Re: mpd: traffic shaping & ttl changing -------------------------------------------------------------------------------- Hi Alex Semenyaka! On Mon, 03 Mar 2008 08:32:38 +0300; Alex Semenyaka wrote about 'mpd: traffic shaping & ttl changing': DM>>> Именно этим и плох. Чтобы не было никаких роутеров-мыльниц, wifi, DM>>> случайно поставленных галочек "разрешить другим пользователям DM>>> сети..." У меня не интернет через VPN, у меня просто VPN. EG>> Можно тупо блокировать исходящие от клиента запросы с "неправильным" EG>> ttl, man ipfw про ipttl. AS> Тут человеку законно хочется не проверять пришедший ttl, а управлять своим AS> (что в Linuxе легко делается в iptables, замечу). Какие-то патчи для этого AS> были на http://totalterror.net/src/, но надо проверять их живость. Сейчас в ipfw@ обсуждают приделывание функционала, который позволял бы менять tos, dscp, ttl и df-бит. А так - ну я вон когда мне надо было, быстренько на коленке переделал divert-демона, который умеет фичи iptables по этой части: $ cat ttlchgd.c /*- * Copyright (c) 2000 Ruslan Ermilov * Copyright (c) 2006 Vadim Goncharov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id$ */ #include <sys/param.h> #include <sys/socket.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> #include <err.h> #include <errno.h> #include <fcntl.h> #include <paths.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sysexits.h> #define MAXPIDLEN 9 /* Max decimal pid length in characters. */ char pidfile[MAXPATHLEN] = { '\0' }; char *prog = NULL; static void sigterm_handler(int sig) { (void)unlink(pidfile); exit(0); } /* * Do the "paper work". * - fork and detach from terminal, if needed. * - save my own pid in /var/run/$0.{port#}.pid. */ void okay(int pn, int detach) { int pf; char *p, strpid[MAXPIDLEN + 1]; pid_t pid; if (pidfile[0] == '\0') { p = (char *)rindex(prog, '/'); p = (p == NULL) ? prog : p+1 ; snprintf(pidfile, sizeof(pidfile)-1, "%s%s.%d.pid", _PATH_VARRUN, p, pn); } pf = open(pidfile, O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK, 0644); /* * We couldn't create pid file */ if (pf == -1) { if (errno == EEXIST) { /* * If it is because it's already exists */ bzero(strpid, MAXPIDLEN + 1); fprintf(stderr, "PID file already exists!\n"); /* * Try to read the PID stored in the existing file */ pf = open(pidfile, O_RDONLY); if (pf == -1) { perror("Error opening PID file for reading"); exit(EX_IOERR); } if (read(pf, strpid, MAXPIDLEN) < 0) { perror("Error reading PID file"); exit(EX_IOERR); } pid = atol(strpid); close(pf); /* * We found PID, try to determine, whether process * is running */ if (kill(pid, 0) == 0) { /* * Signal is delivered, though process with * such PID exists */ fprintf(stderr, "%s already running with PID=%d, exiting...\n", prog, pid); exit(1); } else { /* * It seems, like the process is killed, so * we can proceed... */ fprintf(stderr, "Stale PID file, overwriting...\n"); pf = open(pidfile, O_WRONLY | O_TRUNC | O_EXLOCK); if (pf == -1) { perror("Error opening PID file for writing"); exit(EX_IOERR); } } } else { perror("Error creating PID file"); exit(EX_IOERR); } } if (detach) { if (daemon(0, 0) != 0) { close(pf); (void)unlink(pidfile); perror("daemon"); exit(EX_OSERR); } } /* * Set signal handlers and system behaviour. This must be done * before saving PID to prevent small, but possible race condition * when another instance failed to create PID, reads it and tries * to send signal to us. */ siginterrupt(SIGTERM, 1); siginterrupt(SIGHUP, 1); /* Ignore 0th signal, or process may be killed with it by default... */ signal(0, SIG_IGN); signal(SIGINT, sigterm_handler); signal(SIGTERM, sigterm_handler); /* Save our PID to pidfile. */ bzero(strpid, MAXPIDLEN + 1); snprintf(strpid, MAXPIDLEN, "%ld\n", getpid()); if (write(pf, strpid, strlen(strpid)) < 0) { perror("Error writing PID file"); exit(EX_IOERR); } close(pf); } void usage(void) { fprintf(stderr, "usage: %s [-v] [-i] -p port ttl\n", prog); exit(1); } int main(int argc, char *argv[]) { char pkt[IP_MAXPACKET]; ssize_t pktlen, hlen; struct ip *pip = (struct ip *)pkt; struct sockaddr_in sin; socklen_t sinlen; int s; int pflag = 0; int verbose = 0; int increment = 0; u_short port = 0; int ttl; unsigned long sum; uint16_t old; char ch; fd_set fdset; prog = argv[0]; while ((ch = getopt(argc, argv, "ip:v")) != -1) switch (ch) { case 'i': increment = 1; break; case 'p': port = htons(atoi(optarg)); pflag++; break; case 'v': verbose = 1; break; case '?': default: usage(); /* NOTREACHED */ } ttl = atoi(argv[optind]); if (!pflag || ((argc - optind) != 1)) { usage(); /* NOTREACHED */ } if ((s = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1) { err(1, "can't create divert socket"); /* NOTREACHED */ } bzero(&sin, sizeof(sin)); sin.sin_family = PF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = port; if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) { err(1, "can't bind divert socket"); /* NOTREACHED */ } okay(port, !verbose); for (;;) { FD_ZERO(&fdset); FD_SET(s, &fdset); if (select(s + 1, &fdset, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) == -1) { if (errno == EINTR) continue; perror("select"); exit(EX_OSERR); } if (!FD_ISSET(s, &fdset)) continue; sinlen = sizeof(sin); if ((pktlen = recvfrom(s, pkt, sizeof(pkt), 0, (struct sockaddr *)&sin, &sinlen)) == -1) if (errno != EINTR) { warn("read from divert socket failed"); continue; } if (verbose) { fprintf(stderr, "recvfrom(%d) = %d\n", s, pktlen); fprintf(stderr, "packet: ip_src=%s ", inet_ntoa(pip->ip_src)); fprintf(stderr, "ip_dst=%s proto=%d ipid=%d ttl=%d\n", inet_ntoa(pip->ip_dst), pip->ip_p, ntohs(pip->ip_id), pip->ip_ttl); } /* Save old TTL bytes for checksum recomputation. */ old = ntohs(*(uint16_t*)&pip->ip_ttl); /* Actual work - change TTL, with saturation arithmetics. */ if (!increment) pip->ip_ttl = ttl; /* Unconditionally set. */ else if ((long)(pip->ip_ttl + ttl) > 255) pip->ip_ttl = 255; else if ((long)(pip->ip_ttl + ttl) < 0) pip->ip_ttl = 0; else pip->ip_ttl += ttl; /* Adjust IP header checksum, as in RFC 1141. */ sum = old + (~ntohs(*(unsigned short *)&pip->ip_ttl) & 0xffff); sum += ntohs(pip->ip_sum); sum = (sum & 0xffff) + (sum>>16); pip->ip_sum = htons(sum + (sum>>16)); /* XXX Fix boundary zero case (see RFC 1624). */ if (pip->ip_sum == 0xffff) pip->ip_sum = 0; if (verbose) fprintf(stderr, "new ttl = %d\n", pip->ip_ttl); if (sendto(s, pkt, pktlen, 0, (struct sockaddr *)&sin, sinlen) == -1) warn("write to divert socket failed"); } } -- WBR, Vadim Goncharov. ICQ#166852181 mailto:vadim_nuclight@mail.ru [Moderator of RU.ANTI-ECOLOGY][FreeBSD][http://antigreen.org][LJ:/nuclight] --- slrn/0.9.8.1 on FreeBSD 6.2/i386 * Origin: Nuclear Lightning @ Tomsk, TPU AVTF Hostel (2:5020/400@fidonet) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.unix.bsd/336491ec65266.html, оценка из 5, голосов 10
|