GithubHelp home page GithubHelp logo

nabla-c0d3 / sslyze Goto Github PK

View Code? Open in Web Editor NEW
3.1K 139.0 433.0 20.06 MB

Fast and powerful SSL/TLS scanning library.

License: GNU Affero General Public License v3.0

Python 99.93% Dockerfile 0.07%
python ssl scans ssllabs library tls security tls13 sslyze tls-scanning-library

sslyze's Introduction

SSLyze

Run Tests Downloads PyPI version Python version

SSLyze is a fast and powerful SSL/TLS scanning tool and Python library.

SSLyze can analyze the SSL/TLS configuration of a server by connecting to it, in order to ensure that it uses strong encryption settings (certificate, cipher suites, elliptic curves, etc.), and that it is not vulnerable to known TLS attacks (Heartbleed, ROBOT, OpenSSL CCS injection, etc.).

Key features

  • Focus on speed and reliability: SSLyze is a battle-tested tool that is used to reliably scan hundreds of thousands of servers every day.
  • Easy to operationalize: SSLyze can be directly run from CI/CD, in order to continuously check a server against Mozilla's recommended TLS configuration.
  • Fully documented Python API to run scans directly from any Python application, such as a function deployed to AWS Lambda.
  • Support for scanning non-HTTP servers including SMTP, XMPP, LDAP, POP, IMAP, RDP, Postgres and FTP servers.
  • Results of a scan can easily be saved to a JSON file for later processing.
  • And much more!

Quick start

On Windows, Linux (x86 or x64) and macOS, SSLyze can be installed directly via pip:

$ pip install --upgrade pip setuptools wheel
$ pip install --upgrade sslyze
$ python -m sslyze www.yahoo.com www.google.com "[2607:f8b0:400a:807::2004]:443"

It can also be used via Docker:

$ docker run --rm -it nablac0d3/sslyze:6.0.0 www.google.com

Lastly, a pre-compiled Windows executable can be downloaded from the Releases page.

Python API Documentation

A sample script describing how to use the SSLyze's Python API is available at ./api_sample.py.

Full documentation for SSLyze's Python API is available here.

Usage as a CI/CD step

By default, SSLyze will check the server's scan results against Mozilla's recommended "intermediate" TLS configuration, and will return a non-zero exit code if the server is not compliant.

$ python -m sslyze mozilla.com
Checking results against Mozilla's "intermediate" configuration. See https://ssl-config.mozilla.org/ for more details.

mozilla.com:443: OK - Compliant.

The Mozilla configuration to check against can be configured via --mozilla_config={old, intermediate, modern}:

$ python -m sslyze --mozilla_config=modern mozilla.com
Checking results against Mozilla's "modern" configuration. See https://ssl-config.mozilla.org/ for more details.

mozilla.com:443: FAILED - Not compliant.
    * certificate_types: Deployed certificate types are {'rsa'}, should have at least one of {'ecdsa'}.
    * certificate_signatures: Deployed certificate signatures are {'sha256WithRSAEncryption'}, should have at least one of {'ecdsa-with-SHA512', 'ecdsa-with-SHA256', 'ecdsa-with-SHA384'}.
    * tls_versions: TLS versions {'TLSv1.2'} are supported, but should be rejected.
    * ciphers: Cipher suites {'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'} are supported, but should be rejected.

This can be used to easily run an SSLyze scan as a CI/CD step.

Development environment

To setup a development environment:

$ pip install --upgrade pip setuptools wheel
$ pip install -e . 
$ pip install -r requirements-dev.txt

The tests can then be run using:

$ invoke test

License

Copyright (c) 2024 Alban Diquet

SSLyze is made available under the terms of the GNU Affero General Public License (AGPL). See LICENSE.txt for details and exceptions.

sslyze's People

Contributors

bcyrill avatar bkartyas avatar bluec0re avatar c0r0n3r avatar codyd51 avatar dzsibi avatar ethanarbuckle avatar fabian-hk avatar faheel avatar festivekyle avatar freakboy3742 avatar fwinterborn avatar gerwout avatar glestel avatar hvnsweeting avatar kravietz avatar mxsasha avatar nabla-c0d3 avatar postmodern avatar preflightoptions avatar raheelakhan1172 avatar rseedorff avatar rwg avatar ryankoppenhaver avatar secworks avatar svengo avatar tomrittervg avatar trolldbois avatar tykkz avatar wolfgangkarall avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sslyze's Issues

python command

This is the first line in your code:

#!/usr/bin/env python

Please note that this is not working if you have "python2" and "python3" installed. On my system "python" is a symbolic link for "python3". Change it to:

#!/usr/bin/env python2

Thanks

Socket timeout when test heartbleed

All, I tried to test my site(https://192.168.2.104) if there exist vulnerability of heartbleed but got the socket time out problem. Please help to review below out put.

CHECKING HOST(S) AVAILABILITY


192.168.2.104:443 => 192.168.2.104:443

SCAN RESULTS FOR 192.168.2.104:443 - 192.168.2.104:443


Unhandled exception when processing --heartbleed:
socket.timeout - timed out

I am sure my site (https://192.168.2.104) can be reached in the network.
Is there any reason cause this exception?

Thanks,
Joe

XML schema inconsistencies

I noticed various inconsistencies in the XML schema. Some attributes have the format of Foo_Bar while others are fooBar (ex: <keyExchange>). Also, it seems like <cipherSuite> maybe should be named <cipher>? Certain text values appear to be compound values (ex: sha256WithRSAEncryption and TLS / No ciphers available). I'm not sure how open you are to changing the XML schema, now that users are consuming it.

Help document typo for option resum

All, I found a typo in the help for the option --resum. the word "ressumption" should be "resumption".

please review it .

--resum Tests the server(s) for session ressumption support
using session IDs and TLS session tickets (RFC 5077).

Thanks.

Support connecting to host via proxy

Attempting to scan a host while being behind a corporate proxy leads to this error:

WARNING: Could not connect (timeout); discarding corresponding tasks.

All usual proxy environment variables are set, and other python scripts on my system work through the proxy, so I'm hoping this isn't too tricky to achieve. Will have a dig through the source later myself and see if I can work out what's required.

Cipher suite server preference misidentified

Had a discrepancy between SSLyze and SSLscan over preferred cipher suite for SSLv3. SSLyze thought it was RC4-SHA, SSLscan thought it was DES-CBC3-SHA. Running OpenSSL with -ssl3 returned DES-CBC3-SHA. Also running openssl s_client -ssl3 -cipher DES-CBC3-SHA:RC4-SHA and then openssl s_client -ssl3 -cipher RC4-SHA:DES-CBC3-SHA both returned DES-CBC3-SHA. So it looks like SSLscan was right. Looking into this with Wireshark I can see that individually DES-CBC3-SHA was tested but, when it came to determining preference, DES-CBC3-SHA was missing from the full list sent up in the Client Hello so the server couldn't choose it. I'm afraid I can't provide the target server as it was part of a pentest.

SSLv2 Results still timing out

Looks like the issue from the iSec repo is still present. Issue referenced nassl fix but I'm still seeing this with the latest release:

 CHECKING HOST(S) AVAILABILITY
 -----------------------------

   xxx.xxx.xxx.xxx:7001                => xxx.xxx.xxx.xxx:7001

 SCAN RESULTS FOR xxx.xxx.xxx.xxx:7001 - xxx.xxx.xxx.xxx:7001
 ------------------------------------------------------------

  * SSLV2 Cipher Suites:
      Undefined - An unexpected error happened: 
                 RC4-MD5                             timeout - timed out                
                 RC2-CBC-MD5                         timeout - timed out                
                 IDEA-CBC-MD5                        timeout - timed out                
                 EXP-RC4-MD5                         timeout - timed out                
                 EXP-RC2-CBC-MD5                     timeout - timed out                
                 DES-CBC3-MD5                        timeout - timed out                
                 DES-CBC-MD5                         timeout - timed out                

 SCAN COMPLETED IN 44.06 S

Parse basicConstraints

I noticed the <x509v3BasicConstraints> is a plain string. The BasicConstraints extensions can be defined in short form CA:FALSE pathLen:0 or so called long form. I think it would be useful to fully parse the basic constraints into key:value pairs.

Doesn't back off when STARTTLS isn't supported?

I just ran into an odd case while testing (--starttls=smtp) a Mimecast SMTP server that is triggering SSL errors for us; sslyze doesn't back off when it encounters 'StartTLSError - SMTP STARTTLS not supported'.

I would expect that it stops on first occurence, whenever that occurs, instead of running the full set of tests on a target that will not yield meaningful results anyway? �Should it not stop the moment there is no 'STARTTLS' seen in the server response?

SSLyze on Raspbian

Literally no matter what I do I get the following error when trying to run sslyze:

ERROR: Could not import nassl Python module. Did you clone SSLyze's repo ?

I have built nassl on the system and copied it in to folder, I have downloaded every version of the sslyze I can find 32 bit and 64 bit and I still come up with this error.

These are the OS particulars:

Raspbian
Debian Wheezy
Version: February 2015
Release date: 2015-02-16
Kernel version: 3.18

Any help or push in the right direction would be appreciated.

Allow to hide all outputs

Hello!

I'm currently wanting to use sslyze in a script, running as a cron job. I added the xml_output option, but I still get a lot of output from sslyze — is it possible to get some quiet run? I didn't see anything in the options, and the code doesn't seem to propose this kind of feature (a lot of "print" without any condition).

Would be great if this could be done :).

Cheers,

C.

Parsable tag values

When I export everything to an XML file, could you add
the validity in ISO format also?
e.g. instead of

<validity>
  <notAfter>May  9 21:58:25 2024 GMT</notAfter>
  <notBefore>May 12 21:58:25 2014 GMT</notBefore>
</validity>

it would be great to have the date and time in iso format e.g. with UTC time.

<validity_iso>
  <notAfter>2024-05-09 21:58:25</notAfter>
  <notBefore>2014-05-12 21:58:25</notBefore>
</validity>

and

<publicKeySize>4096 bit</publicKeySize>

would be easier to have as

<publicKeySize>4096</publicKeySize>

as it's always in bit.

cipher suite naming convention

I noticed that sslyze uses hyphenated names (ex: ECDHE-ECDSA-NULL-SHA) but most people identify TLS cipher suites using underscores (ex: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA). Should both names be included in the output? Is there a canonical naming convention for cipher suites?

support for session ticket resumption rate, and possible false negative in ticket resumption

It would be nice to extend --resum_rate to include session ticket resumption tests.

And there is a possibility that session ticket resumption return "false" even though the session is correctly resumed, because it only compares the sent session ticket and returned one, but according RFC 5077, the server may return a renewed session ticket if the ticket encryption key is rotated. I would recommend using the more reliable 'hit' bit in OpenSSL's SSL struct.

Cipher test fails for sites that redirect /

I just tested 0.10 and found that when I run it against a site that redirects / (i.e https://google.com/ to https://google.com/search) to something else the cipher test will fail, here's an example:

  * Session Resumption:
      With Session IDs:                  OK - Supported (5 successful, 0 failed, 0 errors, 5 total attempts).
      With TLS Session Tickets:          OK - Supported

  * TLSV1_2 Cipher Suites:
      Preferred:
                 RC4-SHA                       -              128 bits      HTTP 301 Moved Permanently - /share/
      Accepted:
                 AES256-SHA                    -              256 bits      HTTP 301 Moved Permanently - /share/
                 RC4-SHA                       -              128 bits      HTTP 301 Moved Permanently - /share/
                 AES128-SHA                    -              128 bits      HTTP 301 Moved Permanently - /share/

  * TLSV1_1 Cipher Suites:
      Preferred:
                 RC4-SHA                       -              128 bits      HTTP 301 Moved Permanently - /share/
      Accepted:
                 AES256-SHA                    -              256 bits      HTTP 301 Moved Permanently - /share/
                 RC4-SHA                       -              128 bits      HTTP 301 Moved Permanently - /share/
                 AES128-SHA                    -              128 bits      HTTP 301 Moved Permanently - /share/

  * TLSV1 Cipher Suites:
      Preferred:
                 RC4-SHA                       -              128 bits      HTTP 301 Moved Permanently - /share/
      Accepted:
                 AES256-SHA                    -              256 bits      HTTP 301 Moved Permanently - /share/
                 RC4-SHA                       -              128 bits      HTTP 301 Moved Permanently - /share/
                 AES128-SHA                    -              128 bits      HTTP 301 Moved Permanently - /share/

  * SSLV3 Cipher Suites:
      Server rejected all cipher suites.

sslyze requires write access on startup

I was attempting to install sslyze in /usr/local and run it as a normal user, but got this error:

$ python sslyze.py --regular www.isecpartners.com:443 www.google.com
Traceback (most recent call last):
  File "sslyze.py", line 31, in 
    from plugins import PluginsFinder
ImportError: No module named plugins

After extracting sslyze into my home directory, it worked.

$ python sslyze.py



 REGISTERING AVAILABLE PLUGINS
 -----------------------------

  PluginHSTS
  PluginCertInfo
  PluginSessionRenegotiation
  PluginHeartbleed
  PluginCompression
  PluginOpenSSLCipherSuites
  PluginChromeSha1Deprecation
  PluginSessionResumption



  Command line error: No targets to scan.
  Use -h for help.

Strangle nassl error when testing SSLv3

Ran into this freak error. Cannot seem to reproduce it.

SCAN RESULTS FOR 192.186.208.98:993 - 192.186.208.98:993
--------------------------------------------------------

  * Deflate Compression:
      OK - Compression disabled

Unhandled exception when processing --reneg:
 _nassl.OpenSSLError - error:140940F5:SSL routines:SSL3_READ_BYTES:unexpected record

XML DTD

I'm working on a ruby wrapper to automate sslyze and parse the resulting XML output (a la ruby-nmap). I was wondering if you had a complete DTD for the XML output?

Microsoft root store

Hello!
I find sslyze to be an excellent tool, however I get strange results regarding the Microsoft CA store support. When I test www.verisign.com sslyze says that the SSL certificate on the site is not supported by the Microsoft root store (it says that the certificate has expired). Can the microsoft.pem file somehow be updated in order to rectify this?

Here is the output I get for www.verisign.com :

  • Certificate - Trust:
    Hostname Validation: OK - Subject Alternative Name matches
    "Mozilla NSS - 08/2014" CA Store: OK - Certificate is trusted, Extended Validation
    "Microsoft - 08/2014" CA Store: FAILED - Certificate is NOT Trusted: certificate has expired
    "Apple - OS X 10.9.4" CA Store: OK - Certificate is trusted
    "Java 6 - Update 65" CA Store: OK - Certificate is trusted
    Certificate Chain Received: ['www.verisign.com', 'VeriSign Class 3 Extended Validation SSL SGC CA', 'VeriSign Class 3 Public Primary Certification Authority - G5']

Best wishes,
Thomas Höjemo

Consistent naming for algorithms in XML

<publicKeyAlgorithm/> contains rsaEncryption, where as <signatureAlgorithm/> contains sha256WithRSAEncryption. I feel these should be hyphen separated Strings.

Add better XML attributes for ocspStapling

Every major site I run sslyze against, <ocspStapling/> just contains an error attribute with some text. I feel this needs a status attribute to indicate the result of the test.

Key error on scanning facebook.com

When I scan facebook:

$ ./sslyze.py 173.252.120.6:443 --regular --xml_out fb.xml
----- CUT OUTPUT -----
$ head fb.xml 
<?xml version="1.0" encoding="utf-8"?>
<document SSLyzeVersion="SSLyze v0.10" SSLyzeWeb="https://github.com/nabla-c0d3/sslyze" title="SSLyze Scan Results">
  <invalidTargets/>
  <results defaultTimeout="5" httpsTunnel="None" startTLS="None" totalScanTime="7.17561078072">
    <target host="173.252.120.6" ip="173.252.120.6" port="443">
      <certinfo exception="exceptions.KeyError - 'exponent'"/>
      <compression title="Deflate Compression">
        <compressionMethod isSupported="False" type="DEFLATE"/>
      </compression>
      <heartbleed title="OpenSSL Heartbleed">

You can see it didn't retrieve the certificate chain.
<certinfo exception="exceptions.KeyError - 'exponent'"/>
likely because when parsing some output the value exponent was't found.

$ grep -rn 'exponent' ./* | grep ".py:"
./nassl/X509Certificate.py:186:                         'exponent': self._parse_pubkey_exponent() }
./nassl/X509Certificate.py:220:    def _parse_pubkey_exponent(self):
./plugins/PluginCertInfo.py:337:            self.FIELD_FORMAT("Exponent:", "{0} (0x{0:x})".format(int(certDict['subjectPublicKeyInfo']['publicKey']['exponent'])))]

I'm guessing the issue is in ./plugins/PluginCertInfo.py:337 yet have to find out why. For now I've other deadlines to catch :(

location discovery: unable to find 2 plugins when ran via symlink

I have installed sslyze as a system tool and created a link as below:
/usr/bin/sslyze -> /usr/lib64/sslyze/sslyze.py
It was working fine in the previous version. sslyze 0.10 gives the following error:

  PluginCertInfo - Import Error: [Errno 2] No such file or directory
  PluginChromeSha1Deprecation - Import Error: [Errno 2] No such file or directory

  PluginHeartbleed
  PluginCompression
  PluginSessionResumption
  PluginOpenSSLCipherSuites
  PluginSessionRenegotiation
  PluginHSTS

As you can see, it is unable to find first 2 plugins

Timeout for all checks on a working host

Hello,

This is apparently unrelated with #48 as it doesn't affect only SSLv2.

Here's a sample output:

 SCAN RESULTS FOR aaa.bbb:443 - yyy.yyy.yyy.yyy:443
 ---------------------------------------------------------------

  * Deflate Compression:
      OK - Compression disabled          

  * Session Renegotiation:
      Client-initiated Renegotiations:   OK - Rejected
      Secure Renegotiation:              OK - Supported

Unhandled exception when processing --certinfo: 
socket.timeout - timed out
                 DES-CBC-SHA                         timeout - timed out                
                 AECDH-NULL-SHA                      timeout - timed out                
                 ADH-DES-CBC-SHA                     timeout - timed out                
                 EDH-RSA-DES-CBC3-SHA                TypeError - cannot concatenate 'str' and 'NoneType' objects
                 ECDHE-RSA-DES-CBC3-SHA              TypeError - cannot concatenate 'str' and 'NoneType' objects
                 ECDHE-RSA-AES256-SHA384             TypeError - cannot concatenate 'str' and 'NoneType' objects
                 ECDHE-RSA-AES256-SHA                TypeError - cannot concatenate 'str' and 'NoneType' objects
[…]

It goes on for the other protocols.

Problem: the host is up n'running, working perfectly in a standard browser.

Lemme know of some way to provide the host so that you can test it on your own (host is public, but as I'm not the manager/owner…)

Cheers,

C.

TLS Alert - Wrong version number in version 0.6.

We are running sslyze 0.6 and are overall very happy with it, however we are getting errors checking SSL certs on certain web servers.

The problem is response of:
certinfo exception="utils.SSLyzeSSLConnection.SSLHandshakeRejected - TLS Alert - Wrong version number"

This only occurs when checking a small number of HTTPS servers.

I realise this is an old version, and the problems we are having may have been resolved in more current releases, however at the moment we are not able to upgrade due to the version of python (2.6) on our monitoring servers.

Are you able to provide any advice on how we could resolve this while continuing to run version 0.6?

www reneg issue

Hey :)
I wondering, why there is a different between

python sslyze.py --reneg www.mint.com
and
python sslyze.py --reneg mint.com

If i skip the www, everything is okay. But if I try it with www. it tells me that secure reneg is vuln.
Same with www.airbnb.com

Why is it acting different?

TRUST_STORES_PATH in PluginCertInfo.py

I guess, this:

TRUST_STORES_PATH = join(realpath(dirname(sys.argv[0])), 'plugins',
'data', 'trust_stores')

should rather be:

TRUST_STORES_PATH = join(realpath(dirname(__file__)), 'data',
'trust_stores')

?!

SSLyze on FreeBSD

I didn't test it until now - but will it work on FreeBSD?
In the description is it not mentioned...

hsts problems

If I try --hsts its not giving me the right results. It says no hsts supported by facebook for example. But they support hsts, if I check the headers.
Whats the problem? thx

JSON output?

Hello,

Would you accept a JSON output alongside the current XML?

Purpose:
XML is nice and so, but currently the "trend" is more for JSON, as it's really easy to parse it with some small javascript stuff. It would be a better format in order to display elements on some web page.
Also, having a JSON output allows to take profit of the different types like hash and ordered lists, meaning it might be better if we list Server preferred ciphers in Server order.

I'm pretty sure it won't be that hard, as JSON is just, let's say, a list of hashes (or a hash of lists, or both) and can be pretty easily converted to/from this "object" from/to JSON file.

Also, I'm using sslyze in some script, and its original output was JSON ­— I'm using right now some format conversion process, but that's not really the best way to do what I need ;).

Cheers,

C.

Potential False Positive

In https://github.com/nabla-c0d3/sslyze/blob/master/plugins/PluginSessionRenegotiation.py, there is a potential false positive when testing Jetty Applications. When Jetty is set to reject renegotiation, it actually completes one handshake, and then closes the socket. So an error is not thrown.

You would however, get 'An established connection was aborted by the software in your host machine' when you try to renegotiate once again since the connection is closed after performing 1 handshake.

XML output has elements and child-elements with the same name

With 0.10, the XML output has some elements within parent elements of the same name. Examples:

<heartbleed title="OpenSSL Heartbleed">
    <heartbleed isVulnerable="False"/>
</heartbleed>
<hsts title="HTTP Strict Transport Security">
    <hsts sentHstsHeader="None"/>
</hsts>

This makes it trickier to search for an element in order to read its attributes.

I am assuming that for Heartbleed, you could just roll the boolean into the enclosing element or do what you're doing with chrome_sha1 where the child element is chromeSha1Deprecation. For listing hsts headers, you could rename the element into something like hsts-header.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.