1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-01-22 22:03:54 +03:00

* Renamed udsProxy to udsproxy

* Woring first version proxy
* Added basic sample config file for udsproxy
* Added daemonize example for udsproxy
Fixed os manager treatment of ready
This commit is contained in:
Adolfo Gómez García 2017-01-20 10:29:33 +01:00
parent d42482b6c3
commit 09a49a1cb2
10 changed files with 160 additions and 75 deletions

View File

@ -224,6 +224,7 @@ class Actor(Handler):
try:
res = service.getInstance().osmanager().process(service, message, data, options={'scramble': False})
except Exception as e:
logger.exception("Exception processing from OS Manager")
return Actor.result(six.text_type(e), ERR_OSMANAGER_ERROR)
return Actor.result(res)

View File

@ -98,7 +98,7 @@ class Client(Handler):
logger.debug("Client args for GET: {0}".format(self._args))
if len(self._args) == 0: # Gets version
url = self._request.build_absolute_uri(reverse('ClientDownload'))
url = self._request.build_absolute_uri(reverse('uds.web.views.client_downloads'))
return Client.result({
'availableVersion': CLIENT_VERSION,
'requiredVersion': REQUIRED_CLIENT_VERSION,

View File

@ -51,7 +51,7 @@ import requests
import json
import logging
__updated__ = '2017-01-19'
__updated__ = '2017-01-20'
logger = logging.getLogger(__name__)
@ -360,7 +360,10 @@ class UserServiceManager(object):
UserServiceOpChecker.makeUnique(uService, ui, state)
return False
def notifyPreconnect(self, uService, userName, protocol, proxy=None):
def notifyPreconnect(self, uService, userName, protocol):
proxy = uService.deployed_service.proxy
url = uService.getCommsUrl()
if url is None:
logger.debug('No notification is made because agent does not supports notifications')
@ -371,25 +374,22 @@ class UserServiceManager(object):
try:
data = {'user': userName, 'protocol': protocol}
if proxy is not None:
data = {
'data': data,
'url': url
}
url = proxy.url
r = requests.post(url,
data=json.dumps(data),
headers={'content-type': 'application/json'},
verify=False,
timeout=2)
proxy.doProxyRequest(url=url, data=data, timeout=2)
else:
r = requests.post(url,
data=json.dumps(data),
headers={'content-type': 'application/json'},
verify=False,
timeout=2)
r = json.loads(r.content)
logger.debug('Sent pre connection to client using {}: {}'.format(url, r))
# In fact we ignore result right now
except Exception as e:
logger.info('preConnection failed: {}. Check connection on destination machine: {}'.format(e, url))
def checkUuid(self, uService, proxy=None):
def checkUuid(self, uService):
proxy = uService.deployed_service.proxy
url = uService.getCommsUrl()
@ -404,13 +404,7 @@ class UserServiceManager(object):
try:
if proxy is not None:
r = requests.post(
proxy.url,
data=json.dumps({'url': url}),
headers={'content-type': 'application/json'},
verify=False,
timeout=5
)
proxy.doProxyRequest(url=url, data=None, timeout=5)
else:
r = requests.get(
url,
@ -431,10 +425,12 @@ class UserServiceManager(object):
return True
def sendScript(self, uService, script, proxy=None):
def sendScript(self, uService, script):
'''
If allowed, send script to user service
'''
proxy = uService.deployed_service.proxy
# logger.debug('Senging script: {}'.format(script))
url = uService.getCommsUrl()
if url is None:
@ -445,20 +441,15 @@ class UserServiceManager(object):
try:
data = {'script': script}
if proxy is not None:
data = {
'data': data,
'url': url
}
url = proxy.url
r = requests.post(
url,
data=json.dumps(data),
headers={'content-type': 'application/json'},
verify=False,
timeout=5
)
proxy.doProxyRequest(url=url, data=data, timeout=5)
else:
r = requests.post(
url,
data=json.dumps(data),
headers={'content-type': 'application/json'},
verify=False,
timeout=5
)
r = json.loads(r.content)
logger.debug('Sent script to client using {}: {}'.format(url, r))
# In fact we ignore result right now

View File

@ -42,7 +42,7 @@ from uds.core.util import connection
import six
import logging
__updated__ = '2017-01-19'
__updated__ = '2017-01-20'
logger = logging.getLogger(__name__)
@ -108,10 +108,13 @@ class Transport(Module):
'''
pass
def testServer(self, userService, ip, port):
def testServer(self, userService, ip, port, timeout=4):
# TODO: Add Proxy support here
# GET URL = proxy.../testService?ip=xxxxx&port=yyy&timeout=zzzz
return connection.testServer(ip, six.text_type(port))
proxy = userService.deployed_service.proxy
if proxy is not None:
return proxy.doTestServer(ip, port, timeout)
return connection.testServer(ip, six.text_type(port), timeout)
def isAvailableFor(self, userService, ip):

View File

@ -37,9 +37,9 @@ from django.db import models
from uds.models.UUIDModel import UUIDModel
from uds.models.Tag import TaggingMixin
from uds.models.Util import getSqlDatetime
from django.db.models import signals
import requests
import json
import logging
logger = logging.getLogger(__name__)
@ -63,5 +63,49 @@ class Proxy(UUIDModel, TaggingMixin):
db_table = 'uds_proxies'
app_label = 'uds'
@property
def url(self):
return 'http{}://{}:{}'.format('s' if self.ssl is True else '', self.host, self.port)
@property
def proxyRequestUrl(self):
return self.url + "/proxyRequest"
@property
def testServerUrl(self):
return self.url + "/testServer"
def doProxyRequest(self, url, data=None, timeout=5):
d = {
'url': url
}
if data is not None:
d['data'] = data
return requests.post(
self.proxyRequestUrl,
data=json.dumps(d),
headers={'content-type': 'application/json'},
verify=False,
timeout=timeout
)
def doTestServer(self, ip, port, timeout=5):
try:
url = self.testServerUrl + '?host={}&port={}&timeout={}'.format(ip, port, timeout)
r = requests.get(
url,
timeout=timeout + 1
)
if r.status_code == 302: # Proxy returns "Found" for a success test
return True
# Else returns 404
except Exception:
logger.exception("Getting service state through proxy")
return False
def __unicode__(self):
return 'Proxy {} on {}:{} '.format(self.name, self.host, self.port)

View File

@ -145,6 +145,12 @@ class LinuxOsManager(osmanagers.OSManager):
notifyReady = False
doRemove = False
state = userService.os_state
if msg in ('ready', 'ip'):
if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information..
data = {
'ips': [v.split('=') for v in data.split(',')],
'hostname': userService.friendly_name
}
# Old "info" state, will be removed in a near future
if msg == "info":
@ -166,11 +172,6 @@ class LinuxOsManager(osmanagers.OSManager):
doRemove = True
elif msg == "ip":
# This ocurss on main loop inside machine, so userService is usable
if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information..
data = {
'ips': [v.split('=') for v in data.split(',')],
'hostname': userService.friendly_name
}
state = State.USABLE
self.notifyIp(userService.unique_id, userService, data)
elif msg == "ready":

View File

@ -149,6 +149,14 @@ class WindowsOsManager(osmanagers.OSManager):
* msg = ready, data = None, Informs machine ready to be used
'''
logger.info("Invoked WindowsOsManager for {0} with params: {1},{2}".format(userService, msg, data))
if msg in ('ready', 'ip'):
if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information..
data = {
'ips': [v.split('=') for v in data.split(',')],
'hostname': userService.friendly_name
}
# We get from storage the name for this userService. If no name, we try to assign a new one
ret = "ok"
notifyReady = False
@ -179,11 +187,6 @@ class WindowsOsManager(osmanagers.OSManager):
doRemove = True
elif msg == "ip":
# This ocurss on main loop inside machine, so userService is usable
if not isinstance(data, dict): # Old actors, previous to 2.5
data = {
'ips': [v.split('=') for v in data.split(',')],
'hostname': userService.friendly_name
}
state = State.USABLE
self.notifyIp(userService.unique_id, userService, data)
elif msg == "ready":

1
udsProxy/daemonize.txt Normal file
View File

@ -0,0 +1 @@
sudo daemonize -p /var/run/udsproxy.pid -l /var/lock/subsys/udsproxy -u nobody /home/dkmaster/projects/uds/openuds/udsProxy/bin/udsproxy

View File

@ -2,6 +2,7 @@ package main
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
@ -9,6 +10,8 @@ import (
"log"
"net"
"net/http"
"os"
"os/signal"
"strconv"
"strings"
"time"
@ -19,21 +22,26 @@ import (
const configFilename = "/etc/udsproxy.cfg"
var config struct {
Server string // Server Type, "http" or "https"
Port string // Server port
SSLCertificateFile string // Certificate file
SSLCertificateKeyFile string // Certificate key
Broker string // Broker address
UseSSL bool // If use https for connecting with broker: Warning, certificate must be valid on Broker
Server string // Server Type, "http" or "https"
Port string // Server port
SSLCertificateFile string // Certificate file
SSLCertificateKeyFile string // Certificate key
Broker string // Broker address
AllowFrom []string // Allow BROKER requests from this IPS
UseSSL bool // If use https for connecting with broker: Warning, certificate must be valid on Broker
IgnoreCertificates bool // If true, will ignore certificates (when requesting)
}
func validOrigin(w http.ResponseWriter, r *http.Request) error {
if strings.Split(r.RemoteAddr, ":")[0] != config.Broker {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "Access denied")
return errors.New("Invalid Origin")
ip := strings.Split(r.RemoteAddr, ":")[0]
for _, v := range config.AllowFrom {
if v == ip {
return nil
}
}
return nil
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "Access denied")
return errors.New("Invalid Origin")
}
// Test service
@ -43,8 +51,8 @@ func testService(w http.ResponseWriter, r *http.Request) {
}
r.ParseForm()
ip, port, timeOutStr := r.FormValue("ip"), r.FormValue("port"), r.FormValue("timeout")
if ip == "" || port == "" {
host, port, timeOutStr := r.FormValue("host"), r.FormValue("port"), r.FormValue("timeout")
if host == "" || port == "" {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Invalid arguments")
return
@ -55,8 +63,8 @@ func testService(w http.ResponseWriter, r *http.Request) {
timeOut, _ := strconv.Atoi(timeOutStr)
fmt.Println("Args: ", ip, port)
con, err := net.DialTimeout("tcp", ip+":"+port, time.Duration(timeOut)*time.Second)
fmt.Println("Args: ", host, port)
con, err := net.DialTimeout("tcp", host+":"+port, time.Duration(timeOut)*time.Second)
if err == nil {
con.Close()
@ -86,7 +94,7 @@ func proxyRequest(w http.ResponseWriter, r *http.Request) {
if err := dec.Decode(&body); err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Error in Json: %s", err)
log.Fatal(err)
log.Printf("Error decoding json: %s", err)
return
}
@ -104,24 +112,36 @@ func proxyRequest(w http.ResponseWriter, r *http.Request) {
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Error building request: %s", err)
log.Printf("Error building request: %s", err)
return
}
req.Header.Set("Content-Type", "application/json")
// Ignore Certificate
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: config.IgnoreCertificates},
}
client := &http.Client{
Timeout: time.Duration(5) * time.Second,
Timeout: time.Duration(5) * time.Second,
Transport: tr,
}
resp, err := client.Do(req)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Printf("The connection failed %s", err)
fmt.Fprintf(w, "Error in POST: %s", err)
return
}
defer resp.Body.Close() // Ensures closes response
w.WriteHeader(resp.StatusCode)
b, _ := ioutil.ReadAll(resp.Body)
log.Printf("Response: %d, %s", resp.StatusCode, b)
w.Write(b)
}
@ -145,7 +165,7 @@ func main() {
cfg, err := ini.Load(configFilename)
if err != nil {
log.Fatal(err)
log.Fatal(err) // Fatal calss exit
}
// Default config values
config.Port = "9090"
@ -153,13 +173,26 @@ func main() {
// Read config
cfg.MapTo(&config)
log.Printf("Broker address: %s", config.Broker)
log.Printf("Broker: %s", config.Broker)
log.Printf("Server type: %s", config.Server)
log.Printf("Server port: %s", config.Port)
log.Printf("Allow Access from: %s", config.AllowFrom)
// Handle signals
// we make a buffered channel to do not loose signal
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
go func() {
for range c {
fmt.Print("Got Ending signal")
os.Exit(0)
}
}()
http.HandleFunc("/actor", actor) // set router for "actor" requests
http.HandleFunc("/testService", testService) // test service
http.HandleFunc("/testServer", testService) // test service
http.HandleFunc("/proxyRequest", proxyRequest) // Proxy request from broker to service
if config.Server == "https" {
err = http.ListenAndServeTLS(":"+config.Port, config.SSLCertificateFile, config.SSLCertificateKeyFile, nil) // set listen port
} else {
@ -167,8 +200,7 @@ func main() {
}
if err != nil {
log.Fatal("ListenAndServe: ", err)
return
log.Fatal("ListenAndServe: ", err) // Fatal calls exit
}
}

9
udsProxy/udsproxy.cfg Normal file
View File

@ -0,0 +1,9 @@
Server = http
Port = 9090
SSLCertificateFile = /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile = /etc/ssl/private/ssl-cert-snakeoil.key
IgnoreCertificates = True
Broker = https://172.27.0.1:8000
AllowFrom = 172.27.0.1, 127.27.0.8