pax_global_header00006660000000000000000000000064134454051300014511gustar00rootroot0000000000000052 comment=aa367216c07262920151b5179fff883004fa00e4 redir-3.3/000077500000000000000000000000001344540513000124635ustar00rootroot00000000000000redir-3.3/.gitignore000066400000000000000000000002461344540513000144550ustar00rootroot00000000000000*~ *.o .deps autom4te.cache Makefile Makefile.in aclocal.m4 compile config.h config.h.in config.log config.status configure depcomp install-sh missing stamp-h1 redir redir-3.3/.travis.yml000066400000000000000000000034241344540513000145770ustar00rootroot00000000000000# Travis CI integration -- https://travis-ci.org/troglobit/redir # Defaults to GNU GCC and autotools: ./configure && make && make test language: c # Use docker for quicker builds, it now allows https://docs.travis-ci.com/user/apt/ sudo: false # Test build with both GCC and Clang (LLVM) compiler: - gcc - clang env: global: # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # via the "travis encrypt" command using the project repo's public key - secure: "i2bwQa4I+mluvfBk95snxKntMfEIwtXrDYUATcnCJ82vhFjl9pwiy0WSeZgNOj9n2z9p0J0yT7qyvI1z/yqQbZ1ZaeJ0R9SMOQvZZ+gEEHf3o2XdGII+BnsgByWNyu9TGkTp2gco81Annz1P48/sbMlHlcfnq/mHh+wbdm4SexD5uUGPoCIErRObFCGi6VQMbgYHCFTH4z0eVKAb8fabhv78za3/H5fNsljsXwSt63Jn+VhJTCkyts0etz5I7eXlxjAVe5hAXQJughCC0NBS4ZmmAzf2evc9DXjQk24Oq5k8XGYsKGIi9n4hmZGLTTjpC5eYwzrGOjEII0v7bxIWH2d7bIzlLl9LJoGEcM9XBDY7KRK3e/o5ozxo2mCao9lM3gffZUsuSMjIuOmNfpTUP4VvB2fgALPl5towA8QnWc97MueSimJcVZ+bRpKrja79Zke+5LQjnzzOMhOUAn5EZ1sVDaSUR9fS4Q8iaHs99AEaWrkYMpsQQbKAcV5BucPFfsMXGArEwo+nWSwPEgvGkHs4L/wiR+oDkbfjYKSz5g/PhVFh4nN6rEmsx4Q77Um+OLkR/MR9+KDP5JBiB09BkLS6jfJYzst3dJPbmNEDcMJXeQ/JGnt2ld8xbYBezNi0Ef/o06IeBzA1HVDVCTmFwaTBtENu6Pojr11OgeynX18=" addons: apt: packages: - tree coverity_scan: project: name: "troglobit/redir" description: "A TCP port redirector for UNIX" notification_email: troglobit@gmail.com build_command_prepend: "./autogen.sh && ./configure --enable-compat" build_command: "make" branch_pattern: dev # Custom build script for the time being, no "make test" yet script: - ./autogen.sh - ./configure --prefix= --enable-compat - make clean - make -j5 V=1 - DESTDIR=/tmp/tok make install-strip - tree /tmp/tok - ldd /tmp/tok/bin/redir - size /tmp/tok/bin/redir - /tmp/tok/bin/redir -h redir-3.3/AUTHORS000066400000000000000000000014051344540513000135330ustar00rootroot00000000000000Credits should, logically, go to the following people: Nigel Metheringham For taking the code I wrote and making it into a more stable sensible, and usable package. Sam Creasey Original author, but this package would be vastly inferior without Nigel's modifications. Damien Miller Initial TCP wrappers support Thomas Osterried Added the --bind-addr patch. Harald Holzer Added support for FTP connection done by the client Emmanuel Chantréau Added options to simulate a slow connection and to limit bandwidth Joachim Nilsson Current maintainer at https://github.com/troglobit/redir redir-3.3/COPYING000066400000000000000000000432541344540513000135260ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. redir-3.3/ChangeLog.md000066400000000000000000000232321344540513000146360ustar00rootroot00000000000000Change Log ========== All relevant changes to the project are documented in this file. [v3.3][] - 2019-03-23 --------------------- ### Fixes - Fix #5: Use `stdout`, not `stderr`, for `--version` and `--usage` - Fix #6: Minor typo in man page - Fix #8: Update build instructions in README - Fix #9: Major timing bug fix in `--max-bandwidth` and `--random-wait`. Delays below one second are off by a factor 1000! [v3.2][] - 2018-03-10 --------------------- Minor bug fixes. ### Changes - Add missing `transproxy.txt` file to distribution - Update usage text and man page for `--bind` option, w.r.t. transproxy ### Fixes - Issue #4: Service names from `/etc/services` not recognized for compat syntax, `--lport` or `--cport` [v3.1][] - 2017-01-22 --------------------- Restored support for some command line options on behalf of Debian. ### Changes - New `--enable-compat` option added to configure script. Enables support for command line options from v2.x used by `vagrant-lxc`, https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=824698#15 - `--laddr=SRC` - `--lport=PORT` - `--caddr=SRC` - `--cport=PORT` ### Fixes - Portability fixes for musl libc [v3.0][] - 2016-05-06 --------------------- This version changes the command line syntax! You are going to have to change how you call `redir` in order to upgrade. ### Changes - Convert `SRC:PORT` and `DST:PORT` from *options* to *arguments*, using a UNIX syntax that is pretty much standard by now. - Rename `-n,--name=STR` --> `-I,--ident=NAME` - Simplify argument parsing, move more data to global variables - Simplify `debug()` statements, use `syslog()` - Daemonize by default, like a proper UNIX daemon, unless `-n, --foreground` is given - Replace `perror()` and other log messages going to `stderr` in favor of `syslog()` for everything, unless running in foreground, in which case we use `LOG_PERROR` for log message output to `stderr` as well ... unless `-s, --syslog` is given - Replace `-d, --debug` with `-l, --loglevel=LEVEL` to control the `syslog()` default log level. The default log level is `LOG_NOTICE` - Convert to GNU Configure & Build System. With configure switches like `--disable-ftp`, `--disable-shaping`, and `--with-libwrap` - Change distribution to use `.tar.xz` rather than `.tar.gz` from now on - Convert to Markdown, clean up and simplify `README` - Remove local versions of `getopt()` and `getopt_long()`. All relevant UNIX distributions should have them by now. - Massive code cleanup and (Linux KNF) coding style fixes - Add Coverity Scan support for Travis-CI runs - Complete rewrite of man page - Overhaul of `--help` usage help - Refactor to reduce code duplication: - `verify_request()` for TCP wrapper handling - `target_init()` for initializing a `struct sockaddr_in` - `target_connect()` to handle creating and connecting a target socket - Refactor to harmonize function and variable names - Cleanup `redir.c` heading and use proper GNU GPL blurb - Make sure to credit all known major contributors in `AUTHORS` file - Removed `redir.lsm` file ### Fixes - Fix socket leaks found by Coverity Scan - Fix unterminated strings returned by `read()`, found by Coverity Scan - Fix ordering bug(s) found by Coverity Scan - Fix `strcpy()` into fixed size buffer found by Coverity Scan - Fix uninitialized `struct sockaddr_in`, found by Coverity Scan - Check `malloc()` return value - Do `gethostbyname()` before every `connect()`, DNS names may change at runtime [v2.3][] - 2016-05-01 --------------------- This is a checkpoint release by the new maintainer, Joachim Nilsson, integrating all (most) of Debian's patches. ### Changes - Rename man page `redir.man` --> `redir.1` - Rename `CHANGES` --> `ChangeLog.md` - Update Linux Software Map, v0.7 --> v2.2 - Don't strip binaries by default. Thanks to Julien Danjou. Closes Debian bug #437898, by Daniel Kahn Gillmor - Clean up questionable formatting in man page, by Daniel Kahn Gillmor - Remove overrides in Makefile to enable hardening, by Tobias Frost ### Fixes - Debian fixes to man page and `--help` text for `--max_bandwidth` by Daniel Kahn Gilmor - Use `ntohs()` to generate comprehensible `debug()`s and `syslog()`s, by Bernd Eckenfels - Fix calls to TCP wrappers, by Daniel Kahn Gillmor - Fix timeouts to only happen after full duration of inactivity, rather than absolute. This patch is a close approximation of Robert de Bath's patch for Debian bug #142382, by Daniel Kahn Gillmor - Build without any warnings from `gcc`, even with `--pedantic`, patch by Daniel Kahn Gillmor - Fix problem with buffer allocation introduced by bandwidth throttling. Closes Debian bug #335288, by Daniel Kahn Gillmor - Cosmetic fixes to man page which could be applied upstream. by Daniel Kahn Gillmor - Ensure that the server socket has `SO_REUSEADDR` and `SO_LINGER` set properly. Closes Debian bug #508140, by Daniel Kahn Gillmor - Handle type casting of variables. Change `size_t` variables to instead use `socklen_t`, warning from `gcc`. Fix by Lucas Kanashiro [v2.2.1][] - 1999-12-26 ----------------------- Bug fix relase by Sam Creasey. ### Changes - Support for traffic shaping by Emmanuel Chantréau. Interesting stuff. I've not tested this in detail personally. - Adds the ability to compile `redir` with lesser functionality for speed. This is documented in the README. ### Fixes - Fix bug in `do_accept()` where non-fatal error codes returned by `accept()` would cause `redir` to terminate entirely. I had recieved reports of this behavior but was unable to find it until sammy.net had to handle the load of the `redir` 2.2 update using `redir` :) All non-fatal error codes might not be covered. But it "got better". [v2.2][] - 1999-12-15 --------------------- ### Changes - Support for redirecting PORT mode FTP connections in addition to PASV mode FTP redirection. Thus `--ftp` is now `--ftp={port,pasv,both}` to determine what should be redirected. The original version of this patch was submitted by Harald Holzer - Adds the `--connect` option, which is useful if you're bouncing your connections through an HTTP proxy server. Use as `--connect=host:port` and this will be the CONNECT line sent to the proxy. [v2.1][] - 1999-06-22 --------------------- Bugfix release ### Fixes - Fix a problem with FTP redirection - Fix (and add) various logging messages - Fix for some of the TCP wrappers code [v2.0][] - 1999-02-11 --------------------- This version changes the command line syntax! You're going to have to change how you call `redir` in order to upgrade, but not by all that much. We now use `--options` for everything, instead of having the rather wonky "if you've got this thing here, something happens" method used before. We apologize for the inconvenience, but this is really a lot less brain damaged. ### Changes - Support for TCP wrappers, thanks to Damien Miller - The `--name` option now sets the TCP wrapper service name as well as the syslog program name, making it possible to run multiple instances of redir with different access controls. Edit the Makefile to enable TCP wrappers. - Actually implement `--transproxy` when running from `inetd`. - Cleaned up `--ftp` support, at least a little. There are probably still improvements to be made here, but, alas. v1.2 - UNKNOWN --------------- Like v0.5, this release was not possible to locate on the Internet anymore. Even using excellent help from . Restoring this change set was not possible, all we have is this change log entry. If you know the release date, please contact me --Joachim ### Changes - Adds the option `--transproxy`, which, when run as super-user on a Linux system which has had transparent proxying compiled into it's kernel, will make connections seem as if they had come from their true origin. See `transproxy.txt` for further discussion of this option ### Fixes - `redir` should now compile and run correctly on systems which lack `getopt_long()` [v1.1][] - 1998-10-31 --------------------- ### Changes - Add the option `--ftp`, which, when redirecting a port to an FTP server, will, when the server wants to initiate a passive connection, redirect another port for that connection [v1.0][] - 1998-08-08 --------------------- This is the first release by Sam Creasey after picking up from v0.7 by Nigel Metheringham. ### Changes - Add the option `--bind-addr`, which can force `redir` to bind to a specific address or interface when making outgoing connections v0.7 - 1998-06-30 ----------------- A cleanup and bug fix release by Nigel Metheringham after the initial v0.5 release by Sam Creasey. v0.5 - UNKNOWN -------------- This release was not possible to locate on the Internet anymore, but is the initial release by Sam Creasey. In his own words: > Redir is actually a horrible hack of my other cool network utility, > daemon, which is actually a horrible hack of ora's using C sample > code, 12.2.c. But, hey, they do something. (and that's the key.) [UNRELEASED]: https://github.com/troglobit/redir/compare/v3.3...HEAD [v3.3]: https://github.com/troglobit/redir/compare/v3.2...v3.3 [v3.2]: https://github.com/troglobit/redir/compare/v3.1...v3.2 [v3.1]: https://github.com/troglobit/redir/compare/v3.0...v3.1 [v3.0]: https://github.com/troglobit/redir/compare/v2.3...v3.0 [v2.3]: https://github.com/troglobit/redir/compare/v2.2.1...v2.3 [v2.2.1]: https://github.com/troglobit/redir/compare/v2.2...v2.2.1 [v2.2]: https://github.com/troglobit/redir/compare/v2.1...v2.2 [v2.1]: https://github.com/troglobit/redir/compare/v2.0...v2.1 [v2.0]: https://github.com/troglobit/redir/compare/v1.1...v2.0 [v1.1]: https://github.com/troglobit/redir/compare/v1.0...v1.1 [v1.0]: https://github.com/troglobit/redir/compare/v0.7...v1.0 redir-3.3/Makefile.am000066400000000000000000000011331344540513000145150ustar00rootroot00000000000000bin_PROGRAMS = redir redir_SOURCES = redir.c dist_man1_MANS = redir.1 doc_DATA = README.md transproxy.txt EXTRA_DIST = $(doc_DATA) ChangeLog.md ## Target to run when building a release release: distcheck @for file in $(DIST_ARCHIVES); do \ md5sum $$file > ../$$file.md5; \ done @mv $(DIST_ARCHIVES) ../ @echo @echo "Resulting release files:" @echo "=================================================================" @for file in $(DIST_ARCHIVES); do \ printf "$$file \tDistribution tarball\n"; \ printf "$$file.md5\t"; cat ../$$file.md5 | cut -f1 -d' '; \ done redir-3.3/README.md000066400000000000000000000132021344540513000137400ustar00rootroot00000000000000A TCP port redirector for UNIX ============================== [![Travis Status][]][Travis] [![Coverity Status]][Coverity Scan] This is a TCP port redirector for UNIX. It can be run under inetd or as standalone (in which case it handles multiple connections). It is 8 bit clean, not limited to line mode, is small and lightweight. If you want access control, run it under xinetd, or inetd with TCP wrappers. Redir listens for TCP connections on a given port, and, when it recieves a connection, then connects to a given destination `address:port`, and pass data between them. It finds most of its applications in traversing firewalls, but, of course, there are other uses. For a UDP port redirector, see [uredir](https://github.com/troglobit/uredir/). Usage ----- Consult the man page for details. Usage: redir [-hinspv] [-b IP] [-f TYPE] [-I NAME] [-l LEVEL] [-t SEC] [-x STR] [-m BPS] [-o FLAG] [-w MSEC] [-z BYTES] [SRC]:PORT [DST]:PORT Options: -b, --bind=IP Force specific IP to bind() to when listening for incoming connections. Not applicable with -p -f, --ftp=TYPE Redirect FTP connections. Where type is one of: 'port', 'pasv', or 'both' -h, --help Show this help text -i, --inetd Run from inetd, SRC:PORT comes from stdin Usage: redir [OPTIONS] [DST]:PORT -I, --ident=NAME Identity, tag syslog messages with NAME Also used as service name for TCP wrappers -l, --loglevel=LEVEL Set log level: none, err, notice*, info, debug -n, --foreground Run in foreground, do not detach from terminal -p, --transproxy Run in Linux's transparent proxy mode -s, --syslog Log messages to syslog -t, --timeout=SEC Set timeout to SEC seconds, default off (0) -v, --version Show program version -x, --connect=STR CONNECT string passed to proxy server Traffic Shaping: -m, --max-bandwidth=BPS Limit the bandwidth to BPS bits/second -o, --wait-in-out=FLAG Wait for in(1), out(2), or in&out(3) -w, --random-wait=MSEC Wait MSEC milliseconds before each packet -z, --bufsize=BYTES Size of the traffic shaping buffer SRC and DST are optional, redir will revert to use 0.0.0.0 (ANY) ### Old Syntax Command line options changed in v3.0. A limited subset of the old syntax is available with the `--enable-compat` configure option. This implicitly also enables `-n` by default. The following subset of the old syntax are available: --lport=PORT Local port (when not running from inetd) --laddr=ADDRESS Local address (when not running from inetd) --cport=PORT Remote port to redirect traffic to --caddr=ADDRESS Remote address to redirect traffic to Examples -------- To redirect port 80 to a webserver listening on loopback port 8080, remember to use `sudo` when using priviliged ports: sudo redir :80 127.0.0.1:8080 This starts `redir` as a standard UNIX daemon in the background, with all log messages sent to the syslog. Use `-n` to foreground and see log messages on `stderr`. To run `redir` from a process monitor like [Finit][] or systemd, tell it to not background itself and to only use the syslog for log messages: redir -n -s :80 127.0.0.1:8080 An `/etc/inetd.conf` line of the same looks very similar: http stream tcp nowait root /usr/sbin/tcpd /usr/bin/redir -n -s -i 127.0.0.1:8080 When running multiple redir instances it can be useful to change how they identify themselves: redir -I nntp www:119 netgate:119 redir -I pop3 ftp:110 netgate:110 This starts an NNTP and a POP3 port redirector, named accordingly. Previously therere was a `redir-wrapper` script included in the distribution, but that is no longer maintained. Building -------- Redir comes with a GNU configure script which you can use to adapt the build to your needs. If you would like to remove support for some extended options (for the sake of speed, code size, whatever), try the following options to configure: --enable-compat Enable limited v2.x command line syntax --disable-shaper Disable traffic shaping code --disable-ftp Disable FTP redirection support The GNU Configure & Build system use `/usr/local` as the default install prefix. For most use-cases this is fine, but if you want to change this to `/usr` use the `--prefix=/usr` configure option: ./configure --prefix=/usr make -j5 sudo make install-strip Building from GIT sources require you have `automake` and `autoconf` installed. Use `./autogen.sh` to create the configure script. Origin & References ------------------- Redir was originally created by [Sam Creasey][] and is now developed and maintained at [GitHub][] by [Joachim Nilsson][]. Use GitHub to file bug reports, clone, or send pull requests for bug fixes and extensions. Redir is distributed under the terms of the GNU Public Licence, version 2 or later, distributed with this source archive in the file COPYING. [Sam Creasey]: http://sammy.net/~sammy/hacks/ [Joachim Nilsson]: http://troglobit.com [GitHub]: https://github.com/troglobit/redir [Finit]: https://github.com/troglobit/finit [Travis]: https://travis-ci.org/troglobit/redir [Travis Status]: https://travis-ci.org/troglobit/redir.png?branch=master [Coverity Scan]: https://scan.coverity.com/projects/8740 [Coverity Status]: https://scan.coverity.com/projects/8740/badge.svg redir-3.3/TODO000066400000000000000000000020611344540513000131520ustar00rootroot00000000000000TODO ==== Unordered list of TODO items. Testing ------- We should add an automated test framework to be run automatically with Travis-CI. At least some simple netcat non-privileged port test should be possible. Test transparent proxy support, since v2.3 that feature has not been looked at even once. See the Linux Documentation/networking/tproxy.txt for more information. My guess is that it'll take some effort to get it working in redir again. -- Joachim Nilsson Non-forking server ------------------ I'm thinking of eventually doing a version which never forks, but does one big-honking-select-loop, which probably wouldn't be much of a bother, and would save a good chunk of ram, but then an FD limit becomes quite a real possibility. perhaps an #ifdef selecting the old or new code would help this... though, really, this is a known problem with a lot of proxies, and it doesn't seem to hurt too bad. depends on the `MAX_FDS` (or whatever that define is. `FD_MAX`?) on your machine. -- Sam Creasey redir-3.3/autogen.sh000077500000000000000000000000541344540513000144630ustar00rootroot00000000000000#!/bin/sh autoreconf -W portability -visfm redir-3.3/configure.ac000066400000000000000000000024721344540513000147560ustar00rootroot00000000000000AC_INIT([redir], [3.3], [https://github.com/troglobit/redir/issues]) AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) AC_CONFIG_SRCDIR([redir.c]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_FILES([Makefile]) AC_PROG_CC AC_PROG_INSTALL AC_HEADER_STDC AC_ARG_ENABLE(compat, AS_HELP_STRING([--enable-compat], [Enable limited v2.x command line syntax])) AC_ARG_ENABLE(shaping, AS_HELP_STRING([--disable-shaping], [Disable traffic shaping support])) AC_ARG_ENABLE(ftp, AS_HELP_STRING([--disable-ftp], [Disable FTP redirection support])) AC_ARG_WITH(libwrap, AS_HELP_STRING([--with-libwrap=DIR], [use libwrap (rooted in DIR), default: yes]), [with_libwrap=$withval], [with_libwrap=yes]) AS_IF([test "x$with_libwrap" != "xno"],[ AS_IF([test -d "$with_libwrap"],[ CPPFLAGS="$CPPFLAGS -I${with_libwrap}/include" LDFLAGS="$LDFLAGS -L${with_libwrap}/" ]) AC_CHECK_LIB(wrap, request_init,, with_libwrap=no) AC_CHECK_HEADER([tcpd.h],, with_libwrap=no) ]) AS_IF([test "x$enable_compat" = "xyes"], [ AC_DEFINE(COMPAT_OPTIONS, 1, [Enable v2.x command line syntax])]) AS_IF([test "x$enable_shaping" != "xno"], enable_shaping="yes", [ AC_DEFINE(NO_SHAPER, 1, [Disable traffic shaping])]) AS_IF([test "x$enable_ftp" != "xno"], enable_ftp="yes", [ AC_DEFINE(NO_FTP, 1, [Disable FTP support])]) AC_OUTPUT redir-3.3/redir.1000066400000000000000000000106351344540513000136570ustar00rootroot00000000000000.Dd 01 May, 2016 .Dt REDIR 1 SMM .Os .Sh NAME .Nm redir .Nd redirect TCP connections .Sh SYNOPSIS .Nm .Op Fl hinpsv .Op Fl b Ar IP .Op Fl f Ar TYPE .Op Fl I Ar NAME .Op Fl l Ar LEVEL .Op Fl m Ar BPS .Op Fl o Ar <1,2,3> .Op Fl t Ar SEC .Op Fl w Ar MSEC .Op Fl x Ar HOST:PORT .Op Fl z Ar BYTES .Ar [SRC]:PORT .Ar [DST]:PORT .Sh DESCRIPTION .Nm redirects TCP connections coming in on a local port, .Ar [SRC]:PORT , to a specified address/port combination, .Ar [DST]:PORT . Both the .Ar SRC and .Ar DST arguments can be left out, .Nm will then use .Ar 0.0.0.0 . .Pp .Nm can be run either from inetd or as a standalone daemon. In .Fl -inetd mode the listening SRC:PORT combo is handled by another process, usually .Nm inetd , and a connected socket is handed over to .Nm via stdin. Hence only .Ar [DST]:PORT is required in .Fl -inetd mode. In standalone mode .Nm can run either in the foreground, .Fl n , or in the background, detached like a proper UNIX daemon. This is the default. When running in the foreground log messages are also printed to stderr, unless the .Fl s flag is given. .Pp Depending on how redir was compiled, not all options may be available. .Sh OPTIONS Mandatory arguments to long options are mandatory for short options too. .Bl -tag -width Ds .It Fl b, Fl -bind=IP Forces .Nm to pick a specific address to bind to when it listens for incoming connections. Not applicable when running in Linux's transparent proxy mode, .Fl p . .It Fl h, -help Show built-in help text. .It Fl f, -ftp=TYPE When using .Nm for an FTP server, this will cause redir to also redirect FTP connections. Type should be specified as either "port", "pasv", or "both", to specify what type of FTP connection to handle. Note that .Fl -transproxy often makes one or the other (generally port) undesirable. .It Fl i, Fl -inetd Run as a process started from .Xr inetd 1 , with the connection passed as stdin and stdout on startup. .It Fl I, Fl -ident=NAME Specify program identity (name) to be used for TCP wrapper checks and syslog messages. .It Fl l, Fl -loglevel=LEVEL Set log level: none, err, notice, info, debug. Default is notice. .It Fl n, Fl -foreground Run in foreground, do not detach from controlling terminal. .It Fl p, Fl -transproxy On a Linux system with transparent proxying enabled, causes .Nm to make connections appear as if they had come from their true origin. See the file transproxy.txt in the distribution, and the Linux Documentation/networking/tproxy.txt for details. Untested on modern Linux kernels. .It Fl s, Fl -syslog Log messages to syslog. Default, except when .Fl n is enabled. .It Fl t, Fl -timeout=SEC Timeout and close the connection after SEC seconds of inactivity. .It Fl v Show program version. .It Fl x, Fl -connect Redirects connections through an HTTP proxy which supports the CONNECT command. Specify the address and port of the proxy using .Ar [DST]:PORT . .Fl -connect requires the hostname and port which the HTTP proxy will be asked to connect to. .El .Sh TRAFFIC SHAPING The following options control traffic shaping, if .Nm is built with shaping enabled. .Bl -tag -width Ds .It Fl m, Fl -max-bandwidth=BPS Reduce the bandwidth to be no more than BPS bits/sec. The algorithm is basic, the goal is to simulate a slow connection, so there is no peak acceptance. .It Fl o, Fl -wait-in-out=<1,2,3> Apply .Fl -max-bandwidth and .Fl -random-wait for input(1), output(2), or both(3). .It Fl w, Fl -random-wait=MSEC Wait between 0 and 2 x n milliseconds before each "packet". A "packet" is a block of data read in one time by redir. A "packet" size is always less than the bufsize (see also .Fl -bufsize ) .It Fl z, Fl -bufsize=BYTES Set the bufsize (default 4096) in bytes. Can be used combined with .Fl -max-bandwidth or .Fl -random-wait to simulate a slow connection. .El .Sh BUGS Command line syntax changed in v3.0. Compatibility with v2.x can be enabled using the .Fl -enable-compat configure option. This enables the following options: .Fl -laddr=ADDR .Fl -lport=PORT .Fl -caddr=ADDR .Fl -cport=PORT which in v3.0 were been replaced with .Ar [SRC]:PORT and .Ar [DST]:PORT . .Pp For full compatibility, using any of these options will implicitly also enable .Fl n . There is currently no way to tell .Nm to background itself in this mode of operation. .Sh SEE ALSO .Xr inetd 1 .Xr uredir 1 .Sh AUTHORS .Nm is written by Nigel Metheringham and Sam Creasey, with contributions from many others. It is currently being maintained at GitHub by Joachim Nilsson. redir-3.3/redir.c000066400000000000000000000633301344540513000137410ustar00rootroot00000000000000/* A TCP port redirector for UNIX * * Copyright (c) 1996-1999 Sam Creasey * Copyright (c) 1996 Nigel Metheringham * Copyright (c) 2016 Joachim Nilsson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see */ #include "config.h" #include #include #include #include #include #include #define SYSLOG_NAMES #include #include #include #include #include #include #include #include #include #include #ifdef USE_TCP_WRAPPERS #include #endif #define FTP_PORT 1 #define FTP_PASV 2 #define REDIR_IN 1 #define REDIR_OUT 0 int inetd = 0; int background = 1; int timeout = 0; int loglevel = LOG_NOTICE; int do_syslog = 0; int transproxy = 0; char *target_addr = NULL; int target_port = 0; char *local_addr = NULL; int local_port = 0; char *bind_addr = NULL; #ifndef NO_FTP int ftp = 0; #endif #ifndef NO_SHAPER int max_bandwidth = 0; int random_wait = 0; int wait_in_out = 3; /* bit 0: wait for "in", bit 1: wait for "out" */ int wait_in = 1; int wait_out = 1; #endif size_t bufsize = BUFSIZ; char *connect_str = NULL; /* CONNECT string passed to proxy */ char *ident = NULL; char *prognm = PACKAGE_NAME; /* prototype anything needing it */ static int client_accept(int sd, struct sockaddr_in *target); static int server_socket(char *addr, int port, int fail); #ifndef NO_SHAPER /* Used in this program to write something in a socket, it has the same parameters and return value as "write", but with the flag "in": true if it's the "in" socket and false if it's the "out" socket */ static inline ssize_t redir_write(int fd, const void *buf, size_t size, int in) { ssize_t result; int wait; wait = in ? wait_in : wait_out; if (random_wait > 0 && wait) { fd_set empty; struct timeval waitbw; /* for bandwidth */ int rand_time; FD_ZERO(&empty); rand_time = rand() % (random_wait * 2); syslog(LOG_DEBUG, "random wait: %u", rand_time); waitbw.tv_sec = rand_time / 1000; waitbw.tv_usec = (rand_time % 1000) * 1000; select(1, &empty, NULL, NULL, &waitbw); } result = write(fd, buf, size); if (max_bandwidth > 0 && wait) { fd_set empty; unsigned long bits; struct timeval waitbw; /* for bandwidth */ FD_ZERO(&empty); /* wait to be sure tu be below the allowed bandwidth */ bits = size * 8; syslog(LOG_DEBUG, "bandwidth wait: %lu", 1000 * bits / max_bandwidth); waitbw.tv_sec = bits / max_bandwidth; waitbw.tv_usec = (1000000 * (bits % max_bandwidth)) / max_bandwidth; select(1, &empty, NULL, NULL, &waitbw); } return result; } #else /* macro if traffic shaper is disabled */ #define redir_write(fd, buf, size, in) write(fd, buf,size) #endif static int usage(int code) { fprintf(stdout,"\n" "Usage: %s [-hinspv] [-b IP] [-f TYPE] [-I NAME] [-l LEVEL] [-t SEC]\n" " [-x STR] [-m BPS] [-o FLAG] [-w MSEC] [-z BYTES]\n" " [SRC]:PORT [DST]:PORT\n", prognm); fprintf(stdout, "\n" "Options:\n" " -b, --bind=IP Force specific IP to bind() to when listening for\n" " incoming connections. Not applicable with -p\n" #ifndef NO_FTP " -f, --ftp=TYPE Redirect FTP connections. Where type is\n" " one of: 'port', 'pasv', or 'both'\n" #endif " -h, --help Show this help text\n" " -i, --inetd Run from inetd, SRC:PORT comes from stdin\n" " Usage: %s [OPTIONS] [DST]:PORT\n" " -I, --ident=NAME Identity, tag syslog messages with NAME\n" #ifdef USE_TCP_WRAPPERS " Also used as service name for TCP wrappers\n" #endif " -l, --loglevel=LEVEL Set log level: none, err, notice*, info, debug\n" " -n, --foreground Run in foreground, do not detach from terminal\n" " -p, --transproxy Run in Linux's transparent proxy mode\n" " -s, --syslog Log messages to syslog\n" " -t, --timeout=SEC Set timeout to SEC seconds, default off (0)\n" " -v, --version Show program version\n" " -x, --connect=STR CONNECT string passed to proxy server\n" #ifdef COMPAT_OPTIONS "\n" "Compatibility options:\n" " --lport=PORT Local port (when not running from inetd)\n" " --laddr=ADDRESS Local address (when not running from inetd)\n" " --cport=PORT Remote port to redirect traffic to\n" " --caddr=ADDRESS Remote address to redirect traffic to\n" #endif #ifndef NO_SHAPER "\n" "Traffic Shaping:\n" " -m, --max-bandwidth=BPS Limit the bandwidth to BPS bits/second\n" " -o, --wait-in-out=FLAG Wait for in(1), out(2), or in&out(3)\n" " -w, --random-wait=MSEC Wait MSEC milliseconds before each packet\n" " -z, --bufsize=BYTES Size of the traffic shaping buffer\n" #endif "\n" "SRC and DST are optional, %s will revert to use 0.0.0.0 (ANY)\n" "Bug report address: %s\n" "\n", prognm, prognm, PACKAGE_BUGREPORT); return code; } static int loglvl(char *level) { int i; for (i = 0; prioritynames[i].c_name; i++) { if (!strcmp(prioritynames[i].c_name, level)) return prioritynames[i].c_val; } return atoi(level); } static int parse_port(char *arg) { int port; struct servent *s; s = getservbyname(arg, "tcp"); if (s != NULL) port = ntohs(s->s_port); else port = atoi(arg); return port; } static int parse_ipport(char *arg, char *buf, size_t len) { char *port; if (!arg || !buf || !len) return -1; port = strchr(arg, ':'); if (!port) return -1; *port++ = 0; snprintf(buf, len, "%s", arg); return parse_port(port); } static char *progname(char *arg0) { char *nm; nm = strrchr(arg0, '/'); if (nm) nm++; else nm = arg0; return nm; } static void parse_args(int argc, char *argv[]) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"bind_addr", required_argument, 0, 'b'}, {"bind", required_argument, 0, 'b'}, {"timeout", required_argument, 0, 't'}, {"inetd", no_argument, 0, 'i'}, {"ident", required_argument, 0, 'I'}, {"loglevel", required_argument, 0, 'l'}, {"name", required_argument, 0, 'I'}, {"syslog", no_argument, 0, 's'}, {"connect", required_argument, 0, 'x'}, #ifndef NO_FTP {"ftp", required_argument, 0, 'f'}, #endif {"transproxy", no_argument, 0, 'p'}, #ifndef NO_SHAPER {"bufsize", required_argument, 0, 'z'}, {"max_bandwidth", required_argument, 0, 'm'}, /* compat */ {"max-bandwidth", required_argument, 0, 'm'}, {"random_wait", required_argument, 0, 'w'}, /* compat */ {"random-wait", required_argument, 0, 'w'}, {"wait_in_out", required_argument, 0, 'o'}, /* compat */ {"wait-in-out", required_argument, 0, 'o'}, #endif #ifdef COMPAT_OPTIONS {"caddr", required_argument, 0, 128}, {"cport", required_argument, 0, 129}, {"laddr", required_argument, 0, 130}, {"lport", required_argument, 0, 131}, #endif {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; extern int optind; int opt, compat = 0; char src[INET6_ADDRSTRLEN] = "", dst[INET6_ADDRSTRLEN] = ""; #ifndef NO_FTP char *ftp_type = NULL; #define FTP_OPTS "f" #else #define FTP_OPTS "" #endif #ifndef NO_SHAPER #define SHAPER_OPTS "m:o:w:z:" #else #define SHAPER_OPTS "" #endif prognm = progname(argv[0]); while ((opt = getopt_long(argc, argv, "b:hiI:l:npst:vx:" FTP_OPTS SHAPER_OPTS, long_options, NULL)) != -1) { switch (opt) { case 'b': bind_addr = optarg; break; #ifndef NO_FTP case 'f': ftp_type = optarg; if (!ftp_type) exit(usage(1)); break; #endif case 'h': exit(usage(0)); case 'i': inetd++; break; case 'I': /* This is the ident which is added to syslog messages */ ident = optarg; break; case 'l': loglevel = loglvl(optarg); if (-1 == loglevel) exit(usage(1)); break; case 'n': background = 0; do_syslog--; break; case 'p': transproxy++; break; case 's': do_syslog++; break; case 't': timeout = atol(optarg); break; #ifndef NO_SHAPER case 'm': max_bandwidth = atol(optarg); break; case 'o': wait_in_out = atol(optarg); wait_in = wait_in_out & 1; wait_out = wait_in_out & 2; break; case 'w': random_wait = atol(optarg); break; case 'z': bufsize = (unsigned int)atol(optarg); if (bufsize < 256) { syslog(LOG_ERR, "Too small buffer (%zd), must be at least 256 bytes!", bufsize); exit(usage(1)); } break; #endif case 'v': fprintf(stdout, "%s\n", PACKAGE_VERSION); exit(0); case 'x': connect_str = optarg; break; #ifdef COMPAT_OPTIONS case 128: /* --caddr=1.2.3.4 */ compat = 1; target_addr = strdup(optarg); break; case 129: /* --cport=80 */ compat = 1; target_port = parse_port(optarg); break; case 130: /* --laddr=127.0.0.1 */ compat = 1; local_addr = strdup(optarg); break; case 131: /* --lport=8080 */ compat = 1; local_port = parse_port(optarg); break; #endif default: exit(usage(1)); } } if (compat) { background = 0; do_syslog--; goto done; } if (optind >= argc) exit(usage(2)); if (inetd) { /* In inetd mode we redirect from src=stdin to dst:port */ target_port = parse_ipport(argv[optind], dst, sizeof(dst)); if (strlen(dst) > 1) target_addr = strdup(dst); } else { /* We need at least [src]:port, if src is left out we listen to any */ local_port = parse_ipport(argv[optind++], src, sizeof(src)); if (-1 == local_port) exit(usage(3)); if (strlen(src) > 1) local_addr = strdup(src); target_port = parse_ipport(argv[optind], dst, sizeof(dst)); if (strlen(dst) > 1) target_addr = strdup(dst); } done: if (!ident) ident = prognm; #ifndef NO_FTP /* some kind of ftp being forwarded? */ if (ftp_type) { if (!strncasecmp(ftp_type, "port", 4)) ftp = FTP_PORT; else if (!strncasecmp(ftp_type, "pasv", 4)) ftp = FTP_PASV; else if (!strncasecmp(ftp_type, "both", 4)) ftp = FTP_PORT | FTP_PASV; else exit(usage(1)); } #endif } #ifndef NO_FTP /* with the --ftp option, this one changes passive mode replies from the ftp server to point to a new redirector which we spawn, now it also change the PORT commando when the client accept the dataconnection */ void ftp_clean(int send, char *buf, ssize_t *bytes, int ftpsrv) { char *port_start; int rporthi, lporthi; int lportlo, rportlo; int lport, rport; int remip[4]; int sd; socklen_t socksize = sizeof(struct sockaddr_in); struct sockaddr_in newsession; struct sockaddr_in sockname; if (ftpsrv == 0) { /* is this a port commando ? */ if (strncmp(buf, "PORT", 4)) { redir_write(send, buf, (*bytes), REDIR_OUT); return; } /* parse the old address out of the buffer */ port_start = strchr(buf, ' '); sscanf(port_start, " %d,%d,%d,%d,%d,%d", &remip[0], &remip[1], &remip[2], &remip[3], &rporthi, &rportlo); } else { /* is this a passive mode return ? */ if (strncmp(buf, "227", 3)) { redir_write(send, buf, (*bytes), REDIR_OUT); return; } /* parse the old address out of the buffer */ port_start = strchr(buf, '('); sscanf(port_start, "(%d,%d,%d,%d,%d,%d", &remip[0], &remip[1], &remip[2], &remip[3], &rporthi, &rportlo); } /* get the outside interface so we can listen */ if (getsockname(send, (struct sockaddr *)&sockname, &socksize) != 0) { syslog(LOG_ERR, "Failed getsockname(): %s", strerror(errno)); exit(1); } rport = (rporthi << 8) | rportlo; /* we need to listen on a port for the incoming connection. we will use the port 0, so let the system pick one. */ sd = server_socket(inet_ntoa(sockname.sin_addr), 0, 1); if (sd == -1) { syslog(LOG_ERR, "Failed creating server socket: %s", strerror(errno)); exit(1); } /* get the real info */ if (getsockname(sd, (struct sockaddr *)&sockname, &socksize) < 0) { syslog(LOG_ERR, "Failed getsockname(): %s", strerror(errno)); exit(1); } lport = ntohs(sockname.sin_port); lporthi = (lport >> 8) & 0xff; lportlo = lport & 0xff; if (ftpsrv == 0) { /* send the new port and ipaddress to the server */ (*bytes) = sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\n", sockname.sin_addr.s_addr & 0xff, (sockname.sin_addr.s_addr >> 8) & 0xff, (sockname.sin_addr.s_addr >> 16) & 0xff, sockname.sin_addr.s_addr >> 24, lporthi, lportlo); } else { /* send the new port and ipaddress to the client */ (*bytes) = sprintf(buf, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\n", sockname.sin_addr.s_addr & 0xff, (sockname.sin_addr.s_addr >> 8) & 0xff, (sockname.sin_addr.s_addr >> 16) & 0xff, sockname.sin_addr.s_addr >> 24, lporthi, lportlo); } newsession.sin_port = htons(rport); newsession.sin_family = AF_INET; newsession.sin_addr.s_addr = remip[0] | (remip[1] << 8) | (remip[2] << 16) | (remip[3] << 24); syslog(LOG_DEBUG, "ftpdata server ip: %s", inet_ntoa(newsession.sin_addr)); syslog(LOG_DEBUG, "ftpdata server port: %d", rport); syslog(LOG_DEBUG, "listening for ftpdata on port %d", lport); syslog(LOG_DEBUG, "listening for ftpdata on addr %s", inet_ntoa(sockname.sin_addr)); /* now that we're bound and listening, we can safely send the new string without fear of them getting a connection refused. */ redir_write(send, buf, (*bytes), REDIR_OUT); /* make a new process to handle the dataconnection correctly, for the PASV mode this isn't a problem because after sending the PASV command, the data connection, get active. For the PORT command the server must send a success, if starting here with the copyloop the success command never arrive the client.*/ switch (fork()) { case -1: /* Error */ syslog(LOG_ERR, "Failed calling fork(): %s", strerror(errno)); _exit(1); case 0: /* Child */ /* turn off ftp checking while the data connection is active */ ftp = 0; client_accept(sd, &newsession); close(sd); _exit(0); default: /* Parent */ close(sd); break; } } #endif static void copyloop(int insock, int outsock, int timeout_secs) { int max_fd; /* Maximum numbered fd used */ struct timeval timeout; ssize_t bytes; ssize_t bytes_in = 0; ssize_t bytes_out = 0; unsigned int start_time, end_time; char *buf; /* Record start time */ start_time = (unsigned int)time(NULL); if (insock > outsock) max_fd = insock; else max_fd = outsock; buf = malloc(bufsize); if (!buf) { syslog(LOG_ERR, "Failed allocating session buffer: %s", strerror(errno)); goto no_mem; } syslog(LOG_DEBUG, "Entering copyloop() - timeout is %d", timeout_secs); while (1) { fd_set iofds; FD_ZERO(&iofds); FD_SET(insock, &iofds); FD_SET(outsock, &iofds); /* Set up timeout, Linux returns seconds left in this structure * so we have to reset it before each select(). */ timeout.tv_sec = timeout_secs; timeout.tv_usec = 0; if (select(max_fd + 1, &iofds, NULL, NULL, (timeout_secs ? &timeout : NULL)) <= 0) { syslog(LOG_DEBUG, "Connection timeout: %d sec", timeout_secs); break; } if (FD_ISSET(insock, &iofds)) { bytes = read(insock, buf, bufsize); if (bytes <= 0) break; /* Make sure to terminate buffer before passing it to ftp_clean() */ buf[bytes] = 0; #ifndef NO_FTP if (ftp & FTP_PORT) /* if we're correcting FTP, lookup for a PORT commando in the buffer, if yes change this and establish a new redirector for the data */ ftp_clean(outsock, buf, &bytes, 0); else #endif if (redir_write(outsock, buf, bytes, REDIR_OUT) != bytes) break; bytes_out += bytes; } if (FD_ISSET(outsock, &iofds)) { bytes = read(outsock, buf, bufsize); if (bytes <= 0) break; /* Make sure to terminate buffer before passing it to ftp_clean() */ buf[bytes] = 0; #ifndef NO_FTP /* if we're correcting for PASV on ftp redirections, then * fix buf and bytes to have the new address, among other * things */ if (ftp & FTP_PASV) ftp_clean(insock, buf, &bytes,1); else #endif if (redir_write(insock, buf, bytes, REDIR_IN) != bytes) break; bytes_in += bytes; } } free(buf); no_mem: shutdown(insock, SHUT_RDWR); shutdown(outsock, SHUT_RDWR); close(insock); close(outsock); end_time = (unsigned int)time(NULL); syslog(LOG_INFO, "Disconnect after %d sec, %ld bytes in, %ld bytes out", (end_time - start_time), bytes_in, bytes_out); } void doproxyconnect(int socket) { int x; char buf[128]; /* write CONNECT string to proxy */ sprintf((char *)&buf, "CONNECT %s HTTP/1.0\n\n", connect_str); x = write(socket, (char *)&buf, strlen(buf)); if (x < 1) { syslog(LOG_ERR, "Failed writing to proxy: %s", strerror(errno)); exit(1); } /* now read result */ x = read(socket, (char *)&buf, sizeof(buf)); if (x < 1) { syslog(LOG_ERR, "Failed reading reply from proxy: %s", strerror(errno)); exit(1); } /* no more error checking for now -- something should be added later */ /* HTTP/1.0 200 Connection established */ } #ifdef USE_TCP_WRAPPERS static int verify_request(int sd) { struct request_info ri; request_init(&ri, RQ_DAEMON, ident, RQ_FILE, sd, 0); sock_host(&ri); sock_hostname(ri.client); sock_hostaddr(ri.client); if (!hosts_access(&ri)) { syslog(LOG_WARNING, "Connection from %s DENIED", eval_client(&ri)); refuse(&ri); return -1; } syslog(LOG_INFO, "Connection from %s ALLOWED", eval_client(&ri)); return 0; } #endif /* USE_TCP_WRAPPERS */ static int target_init(char *addr, int port, struct sockaddr_in *target) { target->sin_family = AF_INET; target->sin_port = htons(port); if (addr) { struct hostent *hp; hp = gethostbyname(addr); if (!hp) { syslog(LOG_ERR, "Unknown host %s", addr); return -1; } syslog(LOG_DEBUG, "target is %s:%d", addr, port); memcpy(&target->sin_addr, hp->h_addr, hp->h_length); } else { syslog(LOG_DEBUG, "target is default, 0.0.0.0:%d", port); target->sin_addr.s_addr = htonl(inet_addr("0.0.0.0")); } return 0; } static int target_connect(int client, struct sockaddr_in *target) { int sd; struct sockaddr_in peer, addr_out; socklen_t peerlen = sizeof(peer); memset(&peer, 0, sizeof(peer)); memset(&addr_out, 0, sizeof(addr_out)); #ifdef USE_TCP_WRAPPERS if (verify_request(client)) return -1; #endif /* USE_TCP_WRAPPERS */ if (!getpeername(client, (struct sockaddr *)&peer, &peerlen)) { syslog(LOG_DEBUG, "peer IP is %s", inet_ntoa(peer.sin_addr)); syslog(LOG_DEBUG, "peer socket is %d", ntohs(peer.sin_port)); } syslog(LOG_DEBUG, "target IP address is %s", inet_ntoa(target->sin_addr)); syslog(LOG_DEBUG, "target port is %d", ntohs(target->sin_port)); if (transproxy) { memcpy(&addr_out, &peer, sizeof(struct sockaddr_in)); addr_out.sin_port = 0; } /* Set up outgoing IP addr (optional) */ if (bind_addr && !transproxy) { struct hostent *hp; addr_out.sin_family = AF_INET; addr_out.sin_port = 0; hp = gethostbyname(bind_addr); if (!hp) { syslog(LOG_ERR, "Failed resolving outbound IP address, %s: %s", bind_addr, strerror(errno)); return -1; } memcpy(&addr_out.sin_addr, hp->h_addr, hp->h_length); syslog(LOG_DEBUG, "IP address for target is %s", inet_ntoa(addr_out.sin_addr)); } sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) { syslog(LOG_ERR, "Failed creating target socket: %s", strerror(errno)); return -1; } if (bind_addr || transproxy) { if (bind(sd, (struct sockaddr *)&addr_out, sizeof(addr_out)) < 0) { syslog(LOG_ERR, "Failed binding to outbound address: %s", strerror(errno)); close(sd); return -1; } } if (connect(sd, (struct sockaddr *)target, sizeof(*target)) < 0) { syslog(LOG_ERR, "Failed connecting to target %s: %s", inet_ntoa(target->sin_addr), strerror(errno)); close(sd); return -1; } syslog(LOG_INFO, "Connecting %s:%d to %s:%d", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port), inet_ntoa(target->sin_addr), ntohs(target->sin_port)); return sd; } static int client_accept(int sd, struct sockaddr_in *target) { int client, status; syslog(LOG_DEBUG, "Waiting for client to connect on server socket ..."); client = accept(sd, NULL, NULL); if (client < 0) { syslog(LOG_ERR, "Failed calling accept(): %s", strerror(errno)); switch(errno) { case EHOSTUNREACH: case ECONNRESET: case ETIMEDOUT: return 0; /* non-fatal errors */ default: return 1; /* all other errors assumed fatal */ } } /* * Double fork here so we don't have to wait later * This detaches us from our parent so that the parent * does not need to pick up dead kids later. * * This needs to be done before the hosts_access stuff, because * extended hosts_access options expect to be run from a child. */ switch (fork()) { case -1: /* Error */ syslog(LOG_ERR, "Server failed fork(): %s", strerror(errno)); close(client); return 1; case 0: /* Child */ break; default: /* Parent */ /* Wait for child (who has forked off grandchild) */ (void)wait(&status); /* Close sockets to prevent confusion */ close(client); return 0; } /* We are now the first child. Fork again and exit */ switch (fork()) { case -1: /* Error */ syslog(LOG_ERR, "Failed duoble fork(): %s", strerror(errno)); _exit(1); case 0: /* Child */ break; default: /* Parent */ _exit(0); } /* We are now the grandchild */ sd = target_connect(client, target); if (sd < 0) _exit(1); /* do proxy stuff */ if (connect_str) doproxyconnect(sd); #ifndef NO_SHAPER /* initialise random number if necessary */ if (random_wait > 0) srand(getpid()); #endif copyloop(client, sd, timeout); exit(0); return 0; } /* * bind to a new socket, we do this out here because passive-fixups * are going to call it too, and there's no sense dupliciting the * code. * * fail is true if we should just return a -1 on error, false if we * should bail. */ static int server_socket(char *addr, int port, int fail) { int ret, sd; struct sockaddr_in server; int reuse_addr = 1; /* allow address reuse */ struct linger linger_opt = { 0, 0}; /* do not linger */ /* * Get a socket to work with. This socket will * be in the Internet domain, and will be a * stream socket. */ sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) { if (fail) return -1; syslog(LOG_ERR, "Failed creating server socket: %s", strerror(errno)); exit(1); } memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(port); if (addr != NULL) { struct hostent *hp; hp = gethostbyname(addr); if (!hp) { if (fail) { close(sd); return -1; } syslog(LOG_ERR, "Cannot resolve hostname %s: %s", addr, strerror(errno)); exit(1); } syslog(LOG_DEBUG, "listening on %s:%d", addr, port); memcpy(&server.sin_addr, hp->h_addr, hp->h_length); } else { syslog(LOG_DEBUG, "local IP is default, listening on 0.0.0.0:%d", port); server.sin_addr.s_addr = htonl(inet_addr("0.0.0.0")); } ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); if (ret != 0) { if (fail) { close(sd); return -1; } syslog(LOG_ERR, "Failed setting socket option SO_REUSEADDR: %s", strerror(errno)); exit(1); } ret = setsockopt(sd, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); if (ret != 0) { if (fail) { close(sd); return -1; } syslog(LOG_ERR, "Failed setting socket option SO_LINGER: %s", strerror(errno)); exit(1); } /* * Try to bind the address to the socket. */ if (bind(sd, (struct sockaddr *)&server, sizeof(server)) < 0) { if (fail) { close(sd); return -1; } syslog(LOG_ERR, "Failed binding server socket: %s", strerror(errno)); exit(1); } /* * Listen on the socket. */ if (listen(sd, 10) < 0) { if (fail) { close(sd); return -1; } syslog(LOG_ERR, "Failed calling listen() on server socket: %s", strerror(errno)); exit(1); } return sd; } int main(int argc, char *argv[]) { int log_opts = LOG_PID | LOG_CONS | LOG_NDELAY; parse_args(argc, argv); #ifdef LOG_PERROR if (!background && do_syslog < 1) log_opts |= LOG_PERROR; #endif openlog(ident, log_opts, LOG_DAEMON); setlogmask(LOG_UPTO(loglevel)); if (inetd) { int sd; struct sockaddr_in target; memset(&target, 0, sizeof(target)); if (target_init(target_addr, target_port, &target)) return 1; sd = target_connect(STDIN_FILENO, &target); if (sd < 0) return 1; copyloop(STDIN_FILENO, sd, timeout); } else { int sd; if (background) { syslog(LOG_DEBUG, "Daemonizing ..."); if (-1 == daemon(0, 0)) { syslog(LOG_ERR, "Failed daemonizing: %s", strerror(errno)); return 1; } } sd = server_socket(local_addr, local_port, 0); if (sd == -1) { syslog(LOG_ERR, "Failed server_socket(): %s", strerror(errno)); return 1; } while (1) { struct sockaddr_in target; memset(&target, 0, sizeof(target)); if (target_init(target_addr, target_port, &target)) return 1; if (client_accept(sd, &target)) return 1; } } return 0; } redir-3.3/transproxy.txt000066400000000000000000000077021344540513000154630ustar00rootroot00000000000000 Transparent proxying support: (with much thanks to Bernd Eckenfels, who has been maintaing redir for debian, and pointed out to me that this could be done at all.) Most semi-recent versions of the linux kernel have an option which can be used with IP firewalls entitled "transparent proxying". Basically, it allows one to add rules with ipfwadm which will redirect all connections to certain hosts, on certain ports, to a port on the firewall machine. An convienent upshot of this feature is that, when it is enabled, a program running as root may explicitly specify the outgoing address to be used when making a connection to just about anything it pleases, which allows us to, when redirecting a connection, make the connection to the destination machine appear as if it were coming from the system which connected to redir. Also quite convenient is the fact that the program doing this does not actually have to be run using transparent proxy firewalling rules, it simply has to be compiled into the kernel. The net effect of it all is the --transproxy flag, which will use this to make connections "look right" in terms of their originating IP, as long as redir is running on a linux system with this feature compiled into its kernel. (please don't ask me about kernel compiling issues, unless you're sure you have this option turned on, your kernel is otherwise installed/working correctly, and --transproxy isn't operating) Note the following side effects: 1) Use of --transproxy will cause the --bind-addr option to have no effect. Not really a problem, as using them together wouldn't make any sense in the first place. 2) For redirection with --transproxy to work at all, the connection to redir must pass through the firewall. The following example should illustrate this: Let's say that there's a firewall machine running with the internal IP 10.0.0.1, and a netmask of 255.0.0.0 (that is, inside network is considered to encompass the entire 10.0.0.0 network). All machines inside the network are configured to use 10.0.0.1 as their gateway address. We want toredirect all connections to the firewall on port 2323 to port 23 on 10.0.0.2, and we'd like to use --transproxy, so we run: redir --transproxy 10.0.0.2 23 2323 Case 1: Connection from the outside world. Let's say someone at address 111.111.111.111 telnets to port 2323, on the external ip address of the firewall machine. Now, as all traffic from inside the firewall to 111.111.111.111 must always pass through the firewall, in any situation, this will work. Case 2: Connection from somewhere on the internal network. Now, someone at 10.0.0.3 wants to connect to the same service, but, rather than telnetting to port 23 on 10.0.0.2, they've telnetted to the port 2323 on 10.0.0.1 (or the external IP of the firewall, doesn't matter). This won't work. This is because when the destination machine (10.0.0.2) saw the connection appearing to come from 10.0.0.3, it then expects the real 10.0.0.3 to be talking to it, which is, in fact not the case. By contrast, in case 1, 10.0.0.2, regardless of the external address, expected these packets to come from the gateway host, which was, in fact, the case. For this reason, internal hosts will be unable to make connections through a redir running with --transproxy enabled. This cannot properly be fixed by redir itself, as far as I can tell, except for using a workaround which would examine the system's routing tables, and then disable the effects of --transproxy when a connection is made from a host in the same routing block as redir's destination. This doesn't sound particularly worthwhile, given that there's no need for an internal machine to hit the redirector at all. Patches will be accepted from someone who bothers to do it, however. Hopefully, you now have a clear understanding of how to use this feature. Questions can be directed to sammy@oh.verio.com. -- Sam Creasey (11/2/98)