Posts Tagged server
Escrevendo um servidor HTTPS em Python
Posted by admin in Programação, Software Livre on May 4th, 2010
Dia desses precisei de um servidor HTTP para implementar algumas funcionalidades que eu precisava. Verificando os que já conhecia, percebi que seria bastente trabalhoso escrever módulos para WebServers como o Lighttpd, Apache ou o Nginx, mesmo apesar deste último ser um pouco mais fácil. Procurei então alguma linguagem interpretada para fazer o que eu precisava.
Pesquisei bastante em Ruby como o fazê-lo, mas não me senti “seduzido” pelas Libs de Ruby que construiam HTTP Servers, e também há aquela velha questão do Ruby ser mono thread. Pesquisei algo relacionado ao Perl mas infelizmente é uma linguagem que não me sinto à vontade para fazer alguma coisa, e sinceramente não gosto muito. No final, acabei escolhendo escrevê-lo em Python, pois devo confessar que existem muitas facilidades devido milhares de modulos embutidos na linguagem em sua instalação padrão.
Uma delas é o BaseHTTPServer, que constrói facilmente um servidor HTTP básico mas extermamente extensível.
O intuito deste POST é mostrar a facilidade com que se constrói um HTTPServer em Python e ainda por cima, adicionar a camada SSL por cima dele.
Escrevendo seu HTTP Server básico com SSL
user@host ~$ vim secureServer.py from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler import ssl class classHandler(BaseHTTPRequestHandler): pass server_addr = (127.0.0.1, 443) httpd = HTTPServer(server_addr, classHandler) httpd.socket = ssl.wrap_socket(httpd.socket, \ certfile='cert.pem', server_side=True, \ ssl_version=ssl.PROTOCOL_SSLv23) while True: httpd.handle_request()
Viram que simples? Mas para este pequeno protótipo funcionar corretamente, é preciso criar um certificado SSL. Como é somente teste, vou criar um “self signed”.
user@host ~$ openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem Generating a 1024 bit RSA private key ..........................................................++++++ .......................++++++ writing new private key to 'cert.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:BR State or Province Name (full name) [Some-State]:São Paulo Locality Name (eg, city) []:SP Organization Name (eg, company) [Internet Widgits Pty Ltd]:Leandro LTDA Organizational Unit Name (eg, section) []:Mail Common Name (eg, YOUR name) []:localhost Email Address []:leandro@localhost
Pronto, agora é só testar com o openssl client.
user@host ~$ openssl s_client -host localhost -port 443 CONNECTED(00000003) depth=0 /C=BR/ST=S\xC3\xA3o Paulo/L=SP/O=Leandro LTDA/OU=Mail/CN=localhost/emailAddress=leandro@localhost verify error:num=18:self signed certificate verify return:1 depth=0 /C=BR/ST=S\xC3\xA3o Paulo/L=SP/O=Leandro LTDA/OU=Mail/CN=localhost/emailAddress=leandro@localhost verify return:1 --- Certificate chain 0 s:/C=BR/ST=S\xC3\xA3o Paulo/L=SP/O=Leandro LTDA/OU=Mail/CN=localhost/emailAddress=leandro@localhost i:/C=BR/ST=S\xC3\xA3o Paulo/L=SP/O=Leandro LTDA/OU=Mail/CN=localhost/emailAddress=leandro@localhost --- Server certificate -----BEGIN CERTIFICATE----- MIIDijCCAvOgAwIBAgIJAKY1XzcnjUW3MA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD VQQGEwJCUjETMBEGA1UECBQKU8OjbyBQYXVsbzELMAkGA1UEBxMCU1AxFTATBgNV BAoTDExlYW5kcm8gTFREQTENMAsGA1UECxMETWFpbDESMBAGA1UEAxMJbG9jYWxo b3N0MSAwHgYJKoZIhvcNAQkBFhFsZWFuZHJvQGxvY2FsaG9zdDAeFw0xMDAxMjEw MTQ0MThaFw0xMTAxMjEwMTQ0MThaMIGLMQswCQYDVQQGEwJCUjETMBEGA1UECBQK U8OjbyBQYXVsbzELMAkGA1UEBxMCU1AxFTATBgNVBAoTDExlYW5kcm8gTFREQTEN MAsGA1UECxMETWFpbDESMBAGA1UEAxMJbG9jYWxob3N0MSAwHgYJKoZIhvcNAQkB FhFsZWFuZHJvQGxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA yCX09Doe3bfFwrmGjAA3cDOUC47vuOVUkWzlnkX2e7nWN7J13amFHtBFXG2YunEs wPEm5VZMMtjq5fhmKdcw+y6U2Lf6iS1Q5vEutuY/L2XbHlzctMFbasqkuVO8H0oB Lqg9zTuRfx/BJ7BmhrWZMKYMYbP/PbFGejMrhMUzcp0CAwEAAaOB8zCB8DAdBgNV HQ4EFgQU6s23dwSaSIO2CRXnzSqRCfbJLyQwgcAGA1UdIwSBuDCBtYAU6s23dwSa SIO2CRXnzSqRCfbJLyShgZGkgY4wgYsxCzAJBgNVBAYTAkJSMRMwEQYDVQQIFApT w6NvIFBhdWxvMQswCQYDVQQHEwJTUDEVMBMGA1UEChMMTGVhbmRybyBMVERBMQ0w CwYDVQQLEwRNYWlsMRIwEAYDVQQDEwlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEW EWxlYW5kcm9AbG9jYWxob3N0ggkApjVfNyeNRbcwDAYDVR0TBAUwAwEB/zANBgkq hkiG9w0BAQUFAAOBgQCl6+gzbq4gQfE/W5NYCX1S/bsNFaGaDoSr8nzibF++3NeI CjgtDciimmSb330AJE1GSC9xqvLF86LV2wvIw3W6eR7+YYgGfoPv2eOnGO/djsKM /0MvPoUjJPfP9k2RftyYQMaKPMXGtGGCWnlm6bUade9wq4BdBYkKRp42Rb83qQ== -----END CERTIFICATE----- subject=/C=BR/ST=S\xC3\xA3o Paulo/L=SP/O=Leandro LTDA/OU=Mail/CN=localhost/emailAddress=leandro@localhost issuer=/C=BR/ST=S\xC3\xA3o Paulo/L=SP/O=Leandro LTDA/OU=Mail/CN=localhost/emailAddress=leandro@localhost --- No client certificate CA names sent --- SSL handshake has read 1072 bytes and written 316 bytes --- New, TLSv1/SSLv3, Cipher is AES256-SHA Server public key is 1024 bit Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : AES256-SHA Session-ID: 0DF03B0D70244E8A4E357504AEB010FCCBF02977E1B530FC8E2F47057AB5D949 Session-ID-ctx: Master-Key: 5E124A87C6BAE38AFF3CA2F78EBDB9A989E988B005AB596D7FCF7D93B48D7FD1C4F1FCAEA325DC48137D0EBC23DDBB4A Key-Arg : None Start Time: 1264038343 Timeout : 300 (sec) Verify return code: 18 (self signed certificate) ---
Pronto, seu HTTPServer com SSL está funcionando. Obviamente, nenhum dos métodos está sendo implementado, mas isto é facilmente de se fazer. O BaseHTTPServer, por padrão não implementa nenhum método, sendo assim, para facilitar você pode extender o SimpleHTTPServer que já implementa os métodos do_GET e do_HEAD, a única coisa que é necessário fazer é implementar os outros método desejado, como do_POST, do_PUT, do_DELETE, etc. Verifique a documentação!
É isso aí galera!!
Referencias
http://docs.python.org/library/ssl.html
http://docs.python.org/library/basehttpserver.html