This commit rewrites the log() function so that it will append a
newline at the end of the message if none is present. It doesn't make
sense to print a log message without a newline since the next log
message (which will write a prefix) expects to be starting at the
beginning of a line.
Although it isn't strictly necessary, this commit also removes any
newlines at the ends of messages. If I missed any, including the
newline at the end of the message will continue to work as it did
before.
Previously, some calls were missing the newline at the end even though
including it was necessary for subsequent messages to appear
correctly.
This code also cleans up some redundant prefixes. The log() method
will prepend the prefix and the different processes should set their
prefix as soon as they start.
Multiline messages are still supported (although the prefix for the
additional lines was changed to match the length of the prefix used
for the first line).
Add an "is_supported()" function to the different methods so that each
method can include whatever logic they wish to indicate if they are
supported on a particular machine. Previously, methods/__init__.py
contained all of the logic for selecting individual methods. Now, it
iterates through a list of possible options and stops on the first
method that it finds that is_supported().
Currently, the decision is made based on the presence of programs in
the PATH. In the future, things such as the platform sshuttle is
running on could be considered.
The server should just read from resolv.conf to find DNS servers to
use. This restores this behavior after the previous commit changed it.
The client now reads both /etc/resolv.conf and
/run/systemd/resolve/resolv.conf. The latter is required to more
reliably intercept regular DNS requests that systemd-resolved makes.
This patch attempts to fix (or aid in debugging) issue #350.
sshuttle didn't explicitly search /sbin and /usr/sbin and they may be
missing in the user's PATH. If PATH is missing, these folders wouldn't
be searched either. There was also a program_exists function which is
redundant to which(). This consolidates everything into the helpers.py
file.
This patch introduces get_path() to return PATH + some extra hardcoded
paths. A new get_env() function can be called to create a consistent
environment when calling external programs. The new which() wrapper
function also ensures we use the same set of paths.
If -vv is supplied, messages clearly indicate the programs we are
looking for, if they are found, and where we looked if we failed to
find them.
I haven't tested the changes to ipfw or pf.
This works for me but needs testing by others. Remember to specify a
::0/0 subnet or similar to route IPv6 through sshuttle.
I'm adding this to nft before nat since it is not sshuttle's default
method on Linux. Documentation updates may be required too.
This patch uses the ipaddress module, but that appears to be included
since Python 3.3.
First, check if TTL indicates we should ignore packet (instead of
checking in multiple rules later). Also, nft method didn't do this at
all. Now, nft matches the behavior of nat.
Second, forward DNS traffic (we may need to intercept traffic to
localhost if a DNS server is running on localhost).
Third, ignore any local traffic packets. (Previously, we ignored local
traffic except DNS and then had the DNS rules). The nft method didn't
do this previously at all. It now matches the behavior of nat.
Lastly, list the subnets to redirect and/or exclude. This step is left
unchanged. Excluding the local port that we are listening on is
redundant with the third step, but should cause no harm.
In summary, this ordering simplifies the rules in nat and eliminates
differences that previously existed between nat and nft.
Without this patch, sshuttle 'restores' /etc/hosts even if it didn't
make any modifications to it. This can be confirmed by running without
--auto-hosts and confirming that the modification time of /etc/hosts
is unchanged while sshuttle is running, but is updated when sshuttle
exits (and a debug2() message is printed indicating the file is
written).
I'm not aware of the previous behavior causing problems. However,
writing an important file unnecessarily as root should be avoided.
Regression was introduced in #337 that is skipping all local traffic,
including DNS. This change makes UDP port 53 (DNS) LOCAL traffic to be
treated as special case.
Fixes#357
* re-organized imports according to pep8
* fixed all remaining pep8 issues
* moved common config into setup.cfg, additionally test `tests`
* removed --select=X -- the errors selected where by default not in
flake8's --ignore list so effectively had no effect
* update .travis.yml to reflect changes in tox.ini
* make travis just use tox in order to avoid code duplaction
* replace py.test with pytest
* fixed .travis.yml
* try different pypy toxenv
* hopefully fixed testenv for pypy
* added pypy basepython, removed unused python2.6
* install dev package before testing (fixes missing coverage)
* fixed empty exception pass blocks with noqa
* Added dummy log message on empty try-except-pass blocks to make dodacy happy :(
* Replaced Exception with BaseException
Before this change, in pf, exclusions used a pass out quick which gave
them higher precedence than any other rule independent of subnet width.
As reported in #265 this causes exclusion from one instance of sshuttle
to also take effect on other instances because quick aborts the
evaluation of rules across all anchors.
This commit changes the precedence of rules so quick can now be
dropped. The new order is defined by the following rule, from
subnet_weight:
"We need to go from smaller, more specific, port ranges, to larger,
less-specific, port ranges. At each level, we order by subnet
width, from most-specific subnets (largest swidth) to
least-specific. On ties, excludes come first."
* Fixes support for OpenBSD (6.1+)
As reported in #219, new versions of OpenBSD ship with a different
pfioc_rule struct. This commit adjusts the offset to match the new struct.
* Fixes tests for OpenBSD 6.1+
Having the tests in a `tests` directory in root is the most common
approach. Also moved pytest's conftest.py into `tests` making the
fixture available for client and server tests.