I have a small code that uploads file to FTPS server (no, SFTP is not an option :( ). However after successful upload SSLError is raised.
from ftplib import FTP_TLS, parse227, parse229
import io
import os
import socket
import six
def ensure_binary(value):
if isinstance(value, six.text_type):
value = value.encode(encoding='utf-8')
return value
class FTP_TLS_Host(FTP_TLS):
"""FTP_TLS class that ignores host from FTP server."""
def makepasv(self):
"""Set passive command, but ignore host from ftp response."""
if self.af == socket.AF_INET:
__, port = parse227(self.sendcmd('PASV'))
host = self.host
else:
host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
return host, port
class FTPSClient(object):
def __init__(self, username, password, hostname, port=990):
self.username = username
self.password = password
self.hostname = hostname
self.port = port
def get_conn(self, ftp_class=FTP_TLS_Host):
conn = ftp_class(timeout=10)
conn.connect(self.hostname, self.port)
conn.login(self.username, self.password)
conn.prot_p()
return conn
def upload(self, content, filename_server):
ftps = self.get_conn()
binary = io.BytesIO(ensure_binary(content))
ftps.storbinary('STOR %s' % filename_server, binary)
ftps_client = FTPSClient(
username=os.environ['FTPS_USERNAME'],
password=os.environ['FTPS_PASSWORD'],
hostname=os.environ['FTPS_HOST'],
port=989,
)
ftps_client.upload('content', 'test.txt')
This is traceback:
File "/test.py", line 54, in <module>
ftps_client.upload('content', 'test.txt')
File "test.py", line 45, in upload
ftps.storbinary('STOR %s' % filename_server, binary)
File "/2.7/lib/python2.7/ftplib.py", line 769, in storbinary
conn.unwrap()
File "/2.7/lib/python2.7/ssl.py", line 823, in unwrap
s = self._sslobj.shutdown()
ssl.SSLError: ('The read operation timed out',)
How do I upload there without getting SSLError?
Reproduction
Make the port 21, target file name dir/test.txt. Put your code in client.py.
openssl req -new -x509 -subj "/CN=ftps-test" -nodes \
-out vsftpd.crt -keyout vsftpd.key
docker run --name=ftps-test -d -e FTP_USER=user -e FTP_PASSWORD=pass \
-v `pwd`/vsftpd.crt:/etc/ssl/certs/vsftpd.crt:ro \
-v `pwd`/vsftpd.key:/etc/ssl/private/vsftpd.key:ro \
panubo/vsftpd vsftpd /etc/vsftpd_ssl.conf
docker exec ftps-test \
bash -c 'mkdir /srv/dir && chown ftp /srv/dir'
export FTPS_USERNAME=user
export FTPS_PASSWORD=pass
export FTPS_HOST=$(docker inspect \
--format '{{ .NetworkSettings.IPAddress }}' ftps-test)
echo "ftps-test $FTPS_HOST" > hosts
export HOSTALIASES=`pwd`/hosts
curl -v --ssl-reqd ftp://ftps-test/ --cacert vsftpd.crt --user user:pass
# Python 2 works as well
python3 client.py
docker exec ftps-test cat /srv/dir/test.txt
docker stop ftps-test && docker rm -v ftps-test
Here is the output:
Generating a 2048 bit RSA private key
..............+++
.................................................................+++
writing new private key to 'vsftpd.key'
-----
fe3ae61591747e3e6acb1da6c14d3c66489f7ce5eed2b836c0463d3342b2a739
* Trying 172.17.0.2...
* Connected to ftps-test (172.17.0.2) port 21 (#0)
< 220 (vsFTPd 3.0.2)
> AUTH SSL
< 234 Proceed with negotiation.
* found 1 certificates in vsftpd.crt
* found 604 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: ftps-test (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: CN=ftps-test
* start date: Fri, 24 Nov 2017 21:39:54 GMT
* expire date: Sun, 24 Dec 2017 21:39:54 GMT
* issuer: CN=ftps-test
* compression: NULL
* ALPN, server did not agree to a protocol
> USER user
< 331 Please specify the password.
> PASS pass
< 230 Login successful.
> PBSZ 0
< 200 PBSZ set to 0.
> PROT P
< 200 PROT now Private.
> PWD
< 257 "/"
* Entry path is '/'
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||4560|).
* Trying 172.17.0.2...
* Connecting to 172.17.0.2 (172.17.0.2) port 4560
* Connected to ftps-test (172.17.0.2) port 21 (#0)
> TYPE A
< 200 Switching to ASCII mode.
> LIST
< 150 Here comes the directory listing.
* Maxdownload = -1
* Doing the SSL/TLS handshake on the data stream
* found 1 certificates in vsftpd.crt
* found 604 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL re-using session ID
* SSL connection using TLS1.2 / RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: ftps-test (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: CN=ftps-test
* start date: Fri, 24 Nov 2017 21:39:54 GMT
* expire date: Sun, 24 Dec 2017 21:39:54 GMT
* issuer: CN=ftps-test
* compression: NULL
* ALPN, server did not agree to a protocol
drwxr-xr-x 2 ftp ftp 4096 Nov 24 21:39 dir
* Remembering we are in dir ""
< 226 Directory send OK.
* Connection #0 to host ftps-test left intact
contentftps-test
ftps-test
Conclusion
The code, as such, is okay. The issue likely lies in your server's configuration.
Related
I'm trying to modify a device in NetBox using subprocess, curl and the NetBox REST API through python.
The issue seems to be with special characters and JSON.
Note: I'm not using requests because we do everything in curl. We are also bypassing security by using the "--insecure" option for curl because this is just a proof-of-concept right now.
The script we are using has two functions:
get: - retrieves all the info for all devices in NetBox and create a file for each device containing it's current 'comments' data. This works just fine.
patch: - grabs the contents of the appropriate device and uploads to NetBox, which should be visible in it's web GUI. This is the function with the issue.
For example, if the file contained
abc
I should be able to change the contents of the file to
now it's more than abc
and then upload the change to NetBox. Looking at the web GUI, I should see the change.
The actual file I am trying to upload to the device comments contains this gibberish, which I typed in manually:
anotyher device needing spellchecking
!##$%^&\*()\_+-=\[\]\\ \[\]\\ /.,,./
did yuou see that?
My upload_comments function:
Note: the {deviceid} in the url comes from a different section of code and is not shown here and is working fine.
def upload_comments(filename):
with open(filename, 'r') as f:
new_comment = f.read().strip()
print('new_comment: ', new_comment) # verify we have content
patch_command_line = f'''curl
--insecure
--verbose
--request PATCH
--header "Content-Type: application/json"
--header "Accept: application/json"
--header "Authorization: Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
--user "xxxx:xxxx"
--url "https://xxx.xxx.xxx.xxx/api/dcim/devices/{deviceid}/"
--data-binary '{{ "comments": "{new_comment}" }}' '''
print(patch_command_line) # verify curl command line
try:
r = subprocess.run(patch_command_line, capture_output=True, shell=True, check=True, timeout=10)
# print("stdout: \n")
print(r.stdout.decode('utf8'))
print(r.stderr.decode('utf8'))
except Exception as e:
print(e)
^
This is the result of running that function:
new_comment: anotyher device needing spellchecking
!##$%^&\*()\_+-=\[\]\\ \[\]\\ /.,,./
did yuou see that?
curl --insecure --verbose --request PATCH --header "Content-Type: application/json" --header "Accept: application/json" --header "Authorization: Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --user "xxxx:xxxx!" --url "https://xxx.xxx.xxx.xxx/api/dcim/devices/2/" --data-binary '{ "comments": "anotyher device needing spellchecking
!##$%^&\*()\_+-=\[\]\\ \[\]\\ /.,,./
did yuou see that?" }'
{"detail":"JSON parse error - Invalid control character at: line 1 column 53 (char 52)"}
* Trying xxx.xxx.xxx.xxx:443...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\* Connected to xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx9) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
} \[5 bytes data\]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} \[512 bytes data\]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ \[122 bytes data\]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ \[21 bytes data\]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ \[892 bytes data\]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ \[264 bytes data\]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ \[52 bytes data\]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} \[1 bytes data\]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} \[52 bytes data\]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* start date: Nov 11 22:51:31 2022 GMT
* expire date: Nov 11 22:51:31 2023 GMT
* issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* SSL certificate verify result: self signed certificate (18), continuing anyway.
} \[5 bytes data\]
> PATCH /api/dcim/devices/2/ HTTP/1.1
> Host: xxx.xxx.xxx.xxx
> User-Agent: curl/7.68.0
> Content-Type: application/json
> Accept: application/json
> Authorization: Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Content-Length: 108
} \[108 bytes data\]
* upload completely sent off: 108 out of 108 bytes
{ \[5 bytes data\]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ \[265 bytes data\]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ \[265 bytes data\]
* old SSL session ID is stale, removing
{ \[5 bytes data\]
* Mark bundle as not supporting multiuse
\< HTTP/1.1 400 Bad Request
\< Date: Tue, 22 Nov 2022 17:03:08 GMT
\< Server: gunicorn
\< Content-Type: application/json
\< Vary: Accept,Cookie,Origin
\< Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
\< API-Version: 3.3
\< X-Content-Type-Options: nosniff
\< Referrer-Policy: same-origin
\< Cross-Origin-Opener-Policy: same-origin
\< X-Frame-Options: SAMEORIGIN
\< Content-Length: 88
\< Connection: close
\<
{ \[5 bytes data\]
100 196 100 88 100 108 245 300 --:--:-- --:--:-- --:--:-- 545
* Closing connection 0
} \[5 bytes data\]
* TLSv1.3 (OUT), TLS alert, close notify (256):
} \[2 bytes data\]
Running curl from the command line gives me the correct result as long as there are no special characters in the value section of comments, otherwise I get errors like this:
{"detail":"JSON parse error - Unterminated string starting at: line 1 column 14 (char 13)"}\* Could not resolve host: november
* Closing connection 1
curl: (6) Could not resolve host: november
curl: (3) unmatched close brace/bracket in URL position 5:
11th}'
^
I have in a Rpi a mosquitto broker with a server TLS certificate signed by a self-signed CA located in the Rpi. I am trying to connect to this broker from a Parrot virtualbox machine using a python script with the following commands:
TLS_CERT_PATH = "/etc/mosquitto/ca.pem"
client_crt = "/etc/mosquitto/VM.pem"
client_key = "/etc/mosquitto/parrot.key"
client.tls_set(ca_certs=TLS_CERT_PATH, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
client.tls_insecure_set(False)
And the following error appears in the broker:
sslv3 alert bad certificate
And in the virtual machine:
certificate verify failed: IP address mismatch
I don't understand the error because if I run in the Virtual machine the following, where 192.168.1.254 is the IP of the Rpi:
mosquitto_pub -h 192.168.1.254 -p 2259 --tls-version tlsv1.2 --cafile /etc/mosquitto/ca.crt --cert /etc/mosquitto/VM.crt --key /etc/mosquitto/parrot.key -t Injecction_moulding/pressure -q 0 -m trying
It doesn't give me any error, even though I am using the same certificate files.
I though that maybe it was something related to an intermediate certificate signing my Virtual machine's client certificate, but it is issued by the same CA that the broker uses. Moreover, I have also added in /etc/ssl/certs, the certificates that I am using just in case the CA was not recognising them as valid certificates.
Any idea of the error? I would appreciate your help because I have spent two days with this and I'm kind of stuck.
What I have in the broker's certificate is:
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
37:4c:1f:f9:cd:80:c7:f4:82:82:04:69:15:5f:25:de:09:60:ae:b9
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = ES, ST = Galicia, L = Vigo, O = TFG, OU = TFG, CN = tfg, emailAddress = myemail
Validity
Not Before: May 25 17:26:29 2022 GMT
Not After : Jul 9 17:26:29 2023 GMT
Subject: C = UK, ST = Galicia, L = Pontevedra, O = Universidad de Vigo, OU = test, CN = 192.168.1.254, emailAddress = myemail
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:b4:85:b7:9b:1e:70:51:9a:0e:af:99:08:26:6f:
55:8e:3a:99:ce:32:c6:8e:23:1b:d4:39:58:75:cc:
c7:9c:5f:3d:a9:f1:f8:85:db:91:9f:25:24:f1:e8:
89:4f:ea:7e:71:23:21:f5:c5:59:77:a6:07:77:53:
e0:9d:12:39:4b:67:b0:10:e0:61:07:d9:fc:fc:f6:
3c:c5:98:f0:70:dd:d1:93:a0:10:64:73:09:8c:63:
de:07:d4:8f:81:18:23:cf:67:60:d6:dd:97:6f:62:
14:ec:0b:20:63:0b:cf:54:ad:78:2d:4d:de:be:29:
01:c1:c1:0f:cb:86:40:e5:2f:0b:29:a3:89:62:03:
6f:f0:ce:b2:43:f6:60:7c:10:46:ea:fd:0e:b4:4b:
ba:64:29:dc:39:50:3d:96:cf:04:c0:43:fa:a6:f3:
bd:e1:da:37:df:19:70:a2:dc:d7:04:2e:2d:b8:27:
97:9c:a3:08:84:be:c6:cf:d6:b6:82:d3:eb:8f:98:
13:eb:39:8b:33:1e:98:72:24:c2:3d:cb:0c:06:3d:
6e:99:fd:a9:f9:02:25:c5:3d:30:76:58:da:33:fa:
6a:33:d1:31:79:15:09:d4:a0:15:df:f2:9a:b9:7e:
68:08:8f:01:73:b7:b5:ac:24:da:bc:0e:d3:0f:b8:
d4:bf
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
25:87:fd:af:41:5a:b2:65:fa:6f:95:12:7f:72:92:ed:ef:8d:
1e:4d:e9:81:ca:75:47:17:a0:b0:0e:20:9e:3e:1a:bf:27:a1:
2f:b4:1f:2b:03:fa:21:ad:2c:da:87:d1:c0:01:12:b4:a0:ce:
29:2e:15:35:50:79:e1:84:3f:05:14:41:f7:e2:17:ee:3c:f7:
6d:32:b7:89:b4:1f:86:e8:89:69:97:a5:33:f3:cd:b5:51:88:
88:41:a5:95:e6:39:44:d4:16:c7:73:19:e1:c5:f1:5e:a7:b3:
a6:d9:9b:16:25:60:6f:ca:3c:0f:1f:85:47:eb:34:24:ad:0b:
74:bb:6b:6f:7a:f1:be:28:4a:fe:6b:55:4b:bd:40:d0:e3:fc:
f4:b7:02:75:86:87:6e:65:f4:91:a4:07:0b:34:a2:f7:88:6a:
3c:d2:67:85:e4:a2:29:5d:02:a3:72:9f:d7:7b:57:8b:c9:ed:
f4:c9:17:00:5b:3d:bc:d4:65:b4:5f:30:12:e1:cb:e2:44:23:
12:05:6f:d4:dd:15:be:56:55:99:d1:7c:f8:8f:34:4e:be:ca:
35:c4:60:03:51:41:ce:98:9a:f4:52:76:b2:69:31:db:3c:1b:
85:b2:04:0b:d8:3d
I am running a Python3 app via Gunicorn with two-way SSL configured. This requires a local cert/key to verify the app as well as a ca_certs file to verify the client. Gunicorn relies on the standard ssl module in Python, particularly the wrap_socket method.
The service starts and responds to curl requests fine when I use self-signed certificates for both server and client authentication. However when I use certificates signed by another CA, I get an error SSL_ERROR_UNKNOWN_CA_ALERT.
A working setup, with self-signed certs:
# Server cert
openssl req \
-newkey rsa:2048 -nodes -keyout domain.key \
-x509 -days 365 -out domain.crt
# Client (CA) cert
openssl req \
-newkey rsa:2048 -nodes -keyout twoway.key \
-x509 -days 365 -out twoway.crt
With Gunicorn configured as follows:
keyfile = domain.key
certfile = domain.crt
cert_reqs = ssl.CERT_REQUIRED
ca_certs=twoway.crt
And curling as follows:
curl -vk --key twoway.key --cert twoway.crt https://my.service
Produces a successful response:
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 5000 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* start date: Dec 7 18:35:54 2018 GMT
* expire date: Dec 7 18:35:54 2019 GMT
* issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /manage/info HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: gunicorn/19.9.0
< Date: Tue, 11 Dec 2018 18:26:19 GMT
< Connection: keep-alive
< Content-Type: application/json
< Content-Length: 73
A failing setup, with a different series of certs:
With Gunicorn configured as follows:
keyfile = my_service_key.key
certfile = my_service_cert.crt
cert_reqs = ssl.CERT_REQUIRED
ca_certs = my_trusted_clients.crt
And curling as follows:
curl -vk --key my_trusted_key.key --cert my_trusted_clients.crt https://my.service
Produces an error:
About to connect() to localhost port 5000 (#0)
Initializing NSS with certpath: sql/etc/pki/nssdb
warning: ignoring value of ssl.verifyhost
skipping SSL peer certificate verification
NSS: client certificate from file
subject: CN=mycn,OU=abc,O=def,...
NSS error -12195
Closing connection #0
SSL connect error
curl: (35) SSL connect error
Any thoughts on whether I am configuring this the wrong way? And why self-signed certs are working but other certs are not?
Note this config worked previously when using Stunnel, where I set the verify level to 4 ("Ignore the chain and only verify the peer certificate."). If there is something similar in Python I believe that would get me in the right direction.
I don't think that this is be possible as of Gunicorn 19.9.
As well as having the complete certificate chain on the server, in order to validate the client/peer certificate, I believe you will need to be able to configure the SSLContext, and especially be able to set ssl.CERT_REQUIRED when in server-mode.
Gunicorn 19.9 (and master at the time of writing) does not currently use the SSLContext-based wrapper on the connection, so this is not possible, see https://github.com/benoitc/gunicorn/issues/1140 .
* Trying x.x.x.x...
* TCP_NODELAY set
* Connected to x.x.x.x (x.x.x.x) port 443 (#0)
> GET /sents HTTP/1.1
> Host: x.x.x.x:443
> User-Agent: curl/7.51.0
> Accept: */*
>
* Recv failure: Connection reset by peer
* Curl_http_done: called premature == 1
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer
^^ Port 80 works fine, 443 and any other port fails. I've tried using flask_sslify on the app, but it fails anyways (the redirect comes out for port 80 though)
ufw status shows 443 as open / lsof shows the app as listening
Not sure if it's a AWS-specific problem, everything works fine on my local machine.
Any help would be greatly appreciated.
I am trying to access a specific website with Python and Tor, but somehow it just loads forever and no response comes.
import requests
import socks
import socket
url = 'http://www.ryanair.com'
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9150)
socket.socket = socks.socksocket
response = requests.get(url)
#no response comes
Some weeks ago it was working. In addition, the same code works still fine for other sites.
My guess would be that it is not a problem on my side, but on the website's side, but I have no clue what can be wrong.
Any ideas of what can be and how it could be solved?
Edit:
If I run the command:
curl --proxy socks5h://127.0.0.1:9150 -vvv http://www.ryanair.com
I get:
* Rebuilt URL to: http://www.ryanair.com/
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 9150 (#0)
> GET / HTTP/1.1
> Host: www.ryanair.com
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 302 Found : Moved Temporarily
< Location: https://www.ryanair.com/
< Connection: close
< Cache-Control: no-cache
< Pragma: no-cache
<
* Closing connection 0
Trying with https:
$ curl --proxy socks5h://127.0.0.1:9150 -vvv https://www.ryanair.com
* Rebuilt URL to: https://www.ryanair.com/
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 9150 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_3DES_EDE_CBC_SHA
* Server certificate: www.ryanair.com
* Server certificate: GeoTrust SSL CA - G3
* Server certificate: GeoTrust Global CA
> GET / HTTP/1.1
> Host: www.ryanair.com
> User-Agent: curl/7.49.1
> Accept: */*
>
#...and it remains here
Edit 2:
I just tried to load this website directly at the Tor browser and it will also keep loading without end.
It will be difficult to run diagnostics without access to your proxy server, but in general, if you're debugging a request, curl is your most invaluable tool.
This should help:
curl --proxy socks5h://127.0.0.1:9150 -vvv http://www.ryanair.com
The -vvv will show you information about the request and the response. That will show you whether your request is well structured or whether the server response is at fault.