Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
6
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
O
onionkit
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Test Cases
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
segfault
onionkit
Commits
d1d9feb6
Commit
d1d9feb6
authored
Mar 04, 2018
by
segfault
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve TorManager
parent
52d1b828
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
35 additions
and
39 deletions
+35
-39
onionkit/service.py
onionkit/service.py
+7
-6
onionkit/tor.py
onionkit/tor.py
+28
-33
No files found.
onionkit/service.py
View file @
d1d9feb6
...
...
@@ -109,6 +109,7 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
self
.
_is_installed
=
self
.
is_installed_file
.
exists
()
self
.
_address
=
self
.
private_key
.
derive_onion_address
()
if
self
.
IsInstalled
else
str
()
self
.
tor
=
TorManager
(
self
.
update_transaction_progress
)
self
.
systemd
=
SystemdManager
(
self
.
Name
)
self
.
container
=
ContainerManager
(
self
.
Name
,
self
.
state_dir
,
self
.
update_transaction_status
,
self
.
update_transaction_progress
)
...
...
@@ -120,7 +121,6 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
self
.
Status
=
Status
.
INSTALLING
try
:
self
.
TransactionStatus
=
_
(
"Starting container to install packages"
)
self
.
container
.
create
()
with
self
.
container
.
run
():
self
.
container
.
install_packages
(
self
.
packages
)
...
...
@@ -157,7 +157,7 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
try
:
if
self
.
IsPublished
:
TorManager
(
self
).
stop_hidden_service
(
)
self
.
tor
.
stop_hidden_service
(
self
.
Address
)
self
.
TransactionStatus
=
_
(
"Stopping container"
)
self
.
container
.
stop
()
...
...
@@ -199,7 +199,8 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
self
.
on_systemd_service_started
()
if
not
self
.
IsPublished
:
TorManager
(
self
).
start_hidden_service
()
self
.
TransactionStatus
=
_
(
"Creating onion service"
)
self
.
tor
.
start_hidden_service
(
self
.
private_key
.
read
(),
self
.
Address
,
self
.
virtual_port
,
self
.
port
)
self
.
Status
=
Status
.
RUNNING
except
Exception
:
...
...
@@ -207,7 +208,7 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
if
self
.
IsRunning
:
self
.
systemd
.
stop
(
self
.
systemd_service
)
if
self
.
IsPublished
:
TorManager
(
self
).
stop_hidden_service
(
)
self
.
tor
.
stop_hidden_service
(
self
.
Address
)
self
.
Status
=
Status
.
ERROR
raise
...
...
@@ -223,7 +224,7 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
self
.
systemd
.
stop
(
self
.
systemd_service
)
if
self
.
IsPublished
:
TorManager
(
self
).
stop_hidden_service
(
)
self
.
tor
.
stop_hidden_service
(
self
.
Address
)
self
.
Status
=
Status
.
STOPPED
except
ServiceAlreadyStoppedError
:
...
...
@@ -316,7 +317,7 @@ class OnionService(DBusObject, metaclass=abc.ABCMeta):
def
IsPublished
(
self
)
->
bool
:
if
not
self
.
Address
:
return
False
return
TorManager
(
self
).
check_hidden_service_published
(
)
return
self
.
tor
.
check_hidden_service_published
(
self
.
Address
)
@
property
def
Address
(
self
)
->
str
:
...
...
onionkit/tor.py
View file @
d1d9feb6
...
...
@@ -6,26 +6,20 @@ from contextlib import contextmanager
import
stem
from
stem.control
import
Controller
,
EventType
from
onionkit
import
_
from
onionkit.util
import
process_mainloop_events
# Only required for type hints
from
typing
import
TYPE_CHECKING
if
TYPE_CHECKING
:
from
onionkit.service
import
OnionService
logger
=
getLogger
()
PUBLICATION_TIMEOUT
=
45
class
HS
Exception
(
Exception
):
class
Tor
Exception
(
Exception
):
pass
class
TorManager
(
object
):
def
__init__
(
self
,
onion_service
:
"OnionService"
):
self
.
onion_service
=
onion_service
def
__init__
(
self
,
progress_callback
:
callable
):
self
.
progress_callback
=
progress_callback
try
:
self
.
controller
=
Controller
.
from_socket_file
()
except
stem
.
SocketError
:
...
...
@@ -33,6 +27,7 @@ class TorManager(object):
raise
self
.
controller
.
authenticate
()
self
.
hs_desc_queue
=
queue
.
Queue
()
self
.
publishing
=
False
@
contextmanager
def
hs_desc_listener
(
self
):
...
...
@@ -44,17 +39,23 @@ class TorManager(object):
finally
:
self
.
controller
.
remove_event_listener
(
hs_desc_listener
)
def
start_hidden_service
(
self
):
def
start_hidden_service
(
self
,
key
:
str
,
address
:
str
,
virtual_port
:
int
,
port
:
int
):
self
.
publishing
=
True
try
:
self
.
_start_hidden_service
(
key
,
address
,
virtual_port
,
port
)
finally
:
self
.
publishing
=
False
def
_start_hidden_service
(
self
,
key_content
:
str
,
address
:
str
,
virtual_port
:
int
,
port
:
int
):
if
not
self
.
tor_circuit_established
():
raise
HS
Exception
(
"No Tor circuit established"
)
raise
Tor
Exception
(
"No Tor circuit established"
)
key_content
=
self
.
onion_service
.
private_key
.
read
()
key_type
=
"RSA1024"
self
.
onion_service
.
TransactionStatus
=
_
(
"Creating onion service"
)
with
self
.
hs_desc_listener
():
response
=
self
.
controller
.
create_ephemeral_hidden_service
(
ports
=
{
self
.
onion_service
.
virtual_port
:
self
.
onion_service
.
port
},
ports
=
{
virtual_port
:
port
},
key_type
=
key_type
,
key_content
=
key_content
,
discard_key
=
False
,
...
...
@@ -63,16 +64,14 @@ class TorManager(object):
)
if
response
.
service_id
:
address
=
response
.
service_id
+
".onion"
if
self
.
onion_service
.
Address
!=
address
:
raise
HSException
(
"Onion address %r does not match precalculated address %r"
%
(
address
,
self
.
onion_service
.
A
ddress
))
response_
address
=
response
.
service_id
+
".onion"
if
address
!=
response_
address
:
raise
TorException
(
"Onion address %r does not match precalculated address %r"
%
(
response_address
,
a
ddress
))
self
.
_wait_for_publication
(
response
)
self
.
onion_service
.
TransactionStatus
=
_
(
"Onion service created"
)
def
stop_hidden_service
(
self
):
self
.
onion_service
.
TransactionStatus
=
"remove hidden service"
self
.
controller
.
remove_ephemeral_hidden_service
(
self
.
onion_service
.
Address
.
replace
(
".onion"
,
""
))
def
stop_hidden_service
(
self
,
address
:
str
):
self
.
controller
.
remove_ephemeral_hidden_service
(
address
.
replace
(
".onion"
,
""
))
def
_wait_for_publication
(
self
,
response
):
directories_uploaded_to
=
list
()
...
...
@@ -82,7 +81,7 @@ class TorManager(object):
while
loop_time
-
start_time
<
PUBLICATION_TIMEOUT
:
# Uploading a descriptor should take 30 seconds (see Tor ticket #20082)
if
loop_time
-
start_time
<
30
:
self
.
onion_service
.
TransactionProgress
=
100
/
30
*
(
loop_time
-
start_time
)
self
.
progress_callback
(
100
/
30
*
(
loop_time
-
start_time
)
)
try
:
event
=
self
.
hs_desc_queue
.
get
(
timeout
=
0
)
...
...
@@ -97,7 +96,7 @@ class TorManager(object):
failures
.
append
(
'%s (%s)'
%
(
event
.
directory_fingerprint
,
event
.
reason
))
if
len
(
directories_uploaded_to
)
==
len
(
failures
):
raise
HS
Exception
(
'Failed to upload our hidden service descriptor to %s'
%
', '
.
join
(
failures
))
raise
Tor
Exception
(
'Failed to upload our hidden service descriptor to %s'
%
', '
.
join
(
failures
))
except
queue
.
Empty
:
for
i
in
range
(
100
):
process_mainloop_events
()
...
...
@@ -105,20 +104,18 @@ class TorManager(object):
loop_time
=
time
.
perf_counter
()
self
.
controller
.
remove_ephemeral_hidden_service
(
response
.
service_id
)
raise
HS
Exception
(
"Timeout reached while trying to upload hidden service descriptor"
)
raise
Tor
Exception
(
"Timeout reached while trying to upload hidden service descriptor"
)
def
check_hidden_service_published
(
self
):
def
check_hidden_service_published
(
self
,
address
:
str
):
# The service id is already in onions/detached when we wait for publication,
# even though we don't know if the publication is successful.
# So we return False if we are currently waiting for publication.
if
self
.
onion_service
.
TransactionStatus
in
(
"start hidden service"
,
"create hidden service"
)
:
if
self
.
publishing
:
return
False
service_id
=
self
.
onion_service
.
Address
.
replace
(
".onion"
,
""
)
controller
=
Controller
.
from_socket_file
()
controller
.
authenticate
()
service_id
=
address
.
replace
(
".onion"
,
""
)
try
:
published_service_ids
=
controller
.
get_info
(
"onions/detached"
).
split
(
"
\n
"
)
published_service_ids
=
self
.
controller
.
get_info
(
"onions/detached"
).
split
(
"
\n
"
)
return
service_id
in
published_service_ids
except
stem
.
ProtocolError
as
e
:
if
e
.
args
==
stem
.
ProtocolError
(
"GETINFO response didn't have an OK status:
\n
"
...
...
@@ -127,6 +124,4 @@ class TorManager(object):
logger
.
error
(
"Got a ProtocolError from stem"
,
exc_info
=
True
)
def
tor_circuit_established
(
self
):
controller
=
Controller
.
from_socket_file
()
controller
.
authenticate
()
return
bool
(
int
(
controller
.
get_info
(
"status/circuit-established"
)))
return
bool
(
int
(
self
.
controller
.
get_info
(
"status/circuit-established"
)))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment