Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply fix from the google group thread to get up and running on Mac OS 10.9 #32

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2268e76
ipfw: don't use 'log' parameter.
apenwarr Jan 2, 2012
89e914e
ui-macos/main.py: fix wait() to avoid deadlock.
apenwarr Jan 2, 2012
e2c6820
firewall: catch SIGHUP and SIGPIPE.
apenwarr Jan 6, 2012
6698992
Use the new arguments from redo v0.10.
Jan 4, 2012
cbc32ff
Import the non-pandoc manpage generator from redo.
apenwarr Jan 6, 2012
41d1f73
Add a --version (-V) option.
apenwarr Jan 6, 2012
4c1a505
firewall.py: workaround MacOS 10.7 Lion bug.
apenwarr Jan 8, 2012
bd20841
firewall.py: clean up repeated calls to ssubprocess.call().
apenwarr Jan 8, 2012
d9f761a
ui-macos: tell the user that we need to reboot on MacOS Lion.
apenwarr Jan 8, 2012
e737f4b
firewall.py: add comments about sysctl problems.
apenwarr Jan 9, 2012
12f6a52
Fix runpython.do for systems with unxpected configurations.
drheld Feb 2, 2012
274ee85
clean.do: don't forget to do version/clean.
apenwarr Feb 7, 2012
42bc6d6
Two small changes to server.py that allow it to run on python2.2
scommab Apr 20, 2012
5743f29
server.py: slightly rearrange previous commit.
apenwarr Jul 1, 2012
cce6a9d
firewall.py: catch SIGINT and SIGTERM too.
apenwarr Jul 6, 2012
bff1610
Document missing --dns option in sshuttle manpage
nomadium Jul 7, 2011
29d2e06
Added --exclude-from feature.
tianyicui Apr 19, 2011
432e98c
auto-hosts: don't add hosts that aren't being routed by sshuttle.
apenwarr Jul 6, 2012
6450c37
hostwatch: handle fully qualified domain names
georgeguimaraes May 20, 2011
860c2a0
Merge branch 'fqdn'
apenwarr Jul 6, 2012
9ce2fa0
README: add a suggestion to try the MacOS GUI app.
apenwarr Aug 11, 2012
04609fd
Thank you good sir. https://groups.google.com/d/msg/sshuttle/1hFK05Ps…
Nov 25, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Documentation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.8
/md-to-man
/*.md.tmp
5 changes: 5 additions & 0 deletions Documentation/all.do
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/bin/ls *.md |
sed 's/\.md/.8/' |
xargs redo-ifchange

redo-always
1 change: 1 addition & 0 deletions Documentation/clean.do
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rm -f *~ .*~ *.8 t/*.8 md-to-man *.tmp t/*.tmp
2 changes: 2 additions & 0 deletions Documentation/default.8.do
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
redo-ifchange md-to-man $2.md.tmp
. ./md-to-man $1 $2 $3
3 changes: 3 additions & 0 deletions Documentation/default.md.tmp.do
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
redo-ifchange ../version/vars $2.md
. ../version/vars
sed -e "s/%VERSION%/$TAG/" -e "s/%DATE%/$DATE/" $2.md
8 changes: 8 additions & 0 deletions Documentation/md-to-man.do
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
redo-ifchange md2man.py
if ./md2man.py </dev/null >/dev/null; then
echo './md2man.py $2.md.tmp'
else
echo "Warning: md2man.py missing modules; can't generate manpages." >&2
echo "Warning: try this: sudo easy_install markdown BeautifulSoup" >&2
echo 'echo Skipping: $2.1 >&2'
fi
278 changes: 278 additions & 0 deletions Documentation/md2man.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
#!/usr/bin/env python
import sys, os, markdown, re
from BeautifulSoup import BeautifulSoup

def _split_lines(s):
return re.findall(r'([^\n]*\n?)', s)


class Writer:
def __init__(self):
self.started = False
self.indent = 0
self.last_wrote = '\n'

def _write(self, s):
if s:
self.last_wrote = s
sys.stdout.write(s)

def writeln(self, s):
if s:
self.linebreak()
self._write('%s\n' % s)

def write(self, s):
if s:
self.para()
for line in _split_lines(s):
if line.startswith('.'):
self._write('\\&' + line)
else:
self._write(line)

def linebreak(self):
if not self.last_wrote.endswith('\n'):
self._write('\n')

def para(self, bullet=None):
if not self.started:
if not bullet:
bullet = ' '
if not self.indent:
self.writeln(_macro('.PP'))
else:
assert(self.indent >= 2)
prefix = ' '*(self.indent-2) + bullet + ' '
self.writeln('.IP "%s" %d' % (prefix, self.indent))
self.started = True

def end_para(self):
self.linebreak()
self.started = False

def start_bullet(self):
self.indent += 3
self.para(bullet='\\[bu]')

def end_bullet(self):
self.indent -= 3
self.end_para()

w = Writer()


def _macro(name, *args):
if not name.startswith('.'):
raise ValueError('macro names must start with "."')
fixargs = []
for i in args:
i = str(i)
i = i.replace('\\', '')
i = i.replace('"', "'")
if (' ' in i) or not i:
i = '"%s"' % i
fixargs.append(i)
return ' '.join([name] + list(fixargs))


def macro(name, *args):
w.writeln(_macro(name, *args))


def _force_string(owner, tag):
if tag.string:
return tag.string
else:
out = ''
for i in tag:
if not (i.string or i.name in ['a', 'br']):
raise ValueError('"%s" tags must contain only strings: '
'got %r: %r' % (owner.name, tag.name, tag))
out += _force_string(owner, i)
return out


def _clean(s):
s = s.replace('\\', '\\\\')
return s


def _bitlist(tag):
if getattr(tag, 'contents', None) == None:
for i in _split_lines(str(tag)):
yield None,_clean(i)
else:
for e in tag:
name = getattr(e, 'name', None)
if name in ['a', 'br']:
name = None # just treat as simple text
s = _force_string(tag, e)
if name:
yield name,_clean(s)
else:
for i in _split_lines(s):
yield None,_clean(i)


def _bitlist_simple(tag):
for typ,text in _bitlist(tag):
if typ and not typ in ['em', 'strong', 'code']:
raise ValueError('unexpected tag %r inside %r' % (typ, tag.name))
yield text


def _text(bitlist):
out = ''
for typ,text in bitlist:
if not typ:
out += text
elif typ == 'em':
out += '\\fI%s\\fR' % text
elif typ in ['strong', 'code']:
out += '\\fB%s\\fR' % text
else:
raise ValueError('unexpected tag %r inside %r' % (typ, tag.name))
out = out.strip()
out = re.sub(re.compile(r'^\s+', re.M), '', out)
return out


def text(tag):
w.write(_text(_bitlist(tag)))


# This is needed because .BI (and .BR, .RB, etc) are weird little state
# machines that alternate between two fonts. So if someone says something
# like foo<b>chicken</b><b>wicken</b>dicken we have to convert that to
# .BI foo chickenwicken dicken
def _boldline(l):
out = ['']
last_bold = False
for typ,text in l:
nonzero = not not typ
if nonzero != last_bold:
last_bold = not last_bold
out.append('')
out[-1] += re.sub(r'\s+', ' ', text)
macro('.BI', *out)


def do_definition(tag):
w.end_para()
macro('.TP')
w.started = True
split = 0
pre = []
post = []
for typ,text in _bitlist(tag):
if split:
post.append((typ,text))
elif text.lstrip().startswith(': '):
split = 1
post.append((typ,text.lstrip()[2:].lstrip()))
else:
pre.append((typ,text))
_boldline(pre)
w.write(_text(post))


def do_list(tag):
for i in tag:
name = getattr(i, 'name', '').lower()
if not name and not str(i).strip():
pass
elif name != 'li':
raise ValueError('only <li> is allowed inside <ul>: got %r' % i)
else:
w.start_bullet()
for xi in i:
do(xi)
w.end_para()
w.end_bullet()


def do(tag):
name = getattr(tag, 'name', '').lower()
if not name:
text(tag)
elif name == 'h1':
macro('.SH', _force_string(tag, tag).upper())
w.started = True
elif name == 'h2':
macro('.SS', _force_string(tag, tag))
w.started = True
elif name.startswith('h') and len(name)==2:
raise ValueError('%r invalid - man page headers must be h1 or h2'
% name)
elif name == 'pre':
t = _force_string(tag.code, tag.code)
if t.strip():
macro('.RS', '+4n')
macro('.nf')
w.write(_clean(t).rstrip())
macro('.fi')
macro('.RE')
w.end_para()
elif name == 'p' or name == 'br':
g = re.match(re.compile(r'([^\n]*)\n +: +(.*)', re.S), str(tag))
if g:
# it's a definition list (which some versions of python-markdown
# don't support, including the one in Debian-lenny, so we can't
# enable that markdown extension). Fake it up.
do_definition(tag)
else:
text(tag)
w.end_para()
elif name == 'ul':
do_list(tag)
else:
raise ValueError('non-man-compatible html tag %r' % name)


PROD='Untitled'
VENDOR='Vendor Name'
SECTION='9'
GROUPNAME='User Commands'
DATE=''
AUTHOR=''

lines = []
if len(sys.argv) > 1:
for n in sys.argv[1:]:
lines += open(n).read().decode('utf8').split('\n')
else:
lines += sys.stdin.read().decode('utf8').split('\n')

# parse pandoc-style document headers (not part of markdown)
g = re.match(r'^%\s+(.*?)\((.*?)\)\s+(.*)$', lines[0])
if g:
PROD = g.group(1)
SECTION = g.group(2)
VENDOR = g.group(3)
lines.pop(0)
g = re.match(r'^%\s+(.*?)$', lines[0])
if g:
AUTHOR = g.group(1)
lines.pop(0)
g = re.match(r'^%\s+(.*?)$', lines[0])
if g:
DATE = g.group(1)
lines.pop(0)
g = re.match(r'^%\s+(.*?)$', lines[0])
if g:
GROUPNAME = g.group(1)
lines.pop(0)

inp = '\n'.join(lines)
if AUTHOR:
inp += ('\n# AUTHOR\n\n%s\n' % AUTHOR).replace('<', '\\<')

html = markdown.markdown(inp)
soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)

macro('.TH', PROD.upper(), SECTION, DATE, VENDOR, GROUPNAME)
macro('.ad', 'l') # left justified
macro('.nh') # disable hyphenation
for e in soup:
do(e)
12 changes: 10 additions & 2 deletions sshuttle.md → Documentation/sshuttle.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
% sshuttle(8) Sshuttle 0.46
% sshuttle(8) Sshuttle %VERSION%
% Avery Pennarun <[email protected]>
% 2011-01-25
% %DATE%

# NAME

Expand Down Expand Up @@ -71,6 +71,10 @@ entire subnet to the VPN.
are taken automatically from the server's routing
table.

--dns
: capture local DNS requests and forward to the remote DNS
server.

--python
: specify the name/path of the remote python interpreter.
The default is just `python`, which means to use the
Expand All @@ -90,6 +94,10 @@ entire subnet to the VPN.
`0/0 -x 1.2.3.0/24` to forward everything except the
local subnet over the VPN, for example.

--exclude-from=*file*
: exclude the subnets specified in a file, one subnet per
line. Useful when you have lots of subnets to exclude.

-v, --verbose
: print more information about the session. This option
can be used more than once for increased verbosity. By
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ This is how you use it:
The above is probably what you want to use to prevent
local network attacks such as Firesheep and friends.

- OR if you have MacOS and want to try the GUI version:
make
open ui-macos/Sshuttle*.app

(You may be prompted for one or more passwords; first, the
local password to become root using either sudo or su, and
then the remote ssh password. Or you might have sudo and ssh set
Expand Down
4 changes: 2 additions & 2 deletions all.do
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
exec >&2
UI=
[ "$(uname)" = "Darwin" ] && UI=ui-macos/all
redo-ifchange sshuttle.8 $UI
redo-ifchange Documentation/all version/all $UI

echo
echo "What now?"
[ -z "$UI" ] || echo "- Try the MacOS GUI: open ui-macos/Sshuttle*.app"
echo "- Run sshuttle: ./sshuttle --dns -r HOSTNAME 0/0"
echo "- Read the README: less README.md"
echo "- Read the man page: less sshuttle.md"
echo "- Read the man page: less Documentation/sshuttle.md"
2 changes: 1 addition & 1 deletion clean.do
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
redo ui-macos/clean
redo ui-macos/clean Documentation/clean version/clean
rm -f *~ */*~ .*~ */.*~ *.8 *.tmp */*.tmp *.pyc */*.pyc
6 changes: 4 additions & 2 deletions client.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,17 @@ def start(self):
raise Fatal('%r expected STARTED, got %r' % (self.argv, line))

def sethostip(self, hostname, ip):
assert(not re.search(r'[^-\w]', hostname))
assert(not re.search(r'[^-\w\.]', hostname))
assert(not re.search(r'[^0-9.]', ip))
self.pfile.write('HOST %s,%s\n' % (hostname, ip))
self.pfile.flush()

def done(self):
self.pfile.close()
rv = self.p.wait()
if rv:
if rv == EXITCODE_NEEDS_REBOOT:
raise FatalNeedsReboot()
elif rv:
raise Fatal('cleanup: %r returned %d' % (self.argv, rv))


Expand Down
2 changes: 1 addition & 1 deletion default.8.do
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
exec >&2
if pandoc </dev/null 2>/dev/null; then
pandoc -s -r markdown -w man -o $3 $1.md
pandoc -s -r markdown -w man -o $3 $2.md
else
echo "Warning: pandoc not installed; can't generate manpages."
redo-always
Expand Down
Loading