Git Product home page Git Product logo

openfortivpn's Introduction

openfortivpn

openfortivpn is a client for PPP+TLS VPN tunnel services. It spawns a pppd process and operates the communication between the gateway and this process.

It is compatible with Fortinet VPNs.

Usage

man openfortivpn

Examples

  • Simply connect to a VPN:

    openfortivpn vpn-gateway:8443 --username=foo
  • Connect to a VPN using an authentication realm:

    openfortivpn vpn-gateway:8443 --username=foo --realm=bar
  • Store password securely with a pinentry program:

    openfortivpn vpn-gateway:8443 --username=foo --pinentry=pinentry-mac
  • Connect with a user certificate and no password:

    openfortivpn vpn-gateway:8443 --username= --password= --user-cert=cert.pem --user-key=key.pem
  • Don't set IP routes and don't add VPN nameservers to /etc/resolv.conf:

    openfortivpn vpn-gateway:8443 -u foo --no-routes --no-dns --pppd-no-peerdns
  • Using a configuration file:

    openfortivpn -c /etc/openfortivpn/my-config

    With /etc/openfortivpn/my-config containing:

    host = vpn-gateway
    port = 8443
    username = foo
    set-dns = 0
    pppd-use-peerdns = 0
    # X509 certificate sha256 sum, trust only this one!
    trusted-cert = e46d4aff08ba6914e64daa85bc6112a422fa7ce16631bff0b592a28556f993db
  • For the full list of config options, see the CONFIGURATION section of

    man openfortivpn

Smartcard

Smartcard support needs openssl pkcs engine and opensc to be installed. The pkcs11-engine from libp11 needs to be compiled with p11-kit-devel installed. Check #464 for a discussion of known issues in this area.

To make use of your smartcard put at least pkcs11: to the user-cert config or commandline option. It takes the full or a partial PKCS#11 token URI.

user-cert = pkcs11:
user-cert = pkcs11:token=someuser
user-cert = pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=012345678;token=someuser
username =
password =

In most cases user-cert = pkcs11: will do it, but if needed you can get the token-URI with p11tool --list-token-urls.

Multiple readers are currently not supported.

Smartcard support has been tested with Yubikey under Linux, but other PIV enabled smartcards may work too. On Mac OS X Mojave it is known that the pkcs engine-by-id is not found.

Installing

Installing existing packages

Some Linux distributions provide openfortivpn packages:

On macOS both Homebrew and MacPorts provide an openfortivpn package. Either install Homebrew then install openfortivpn:

# Install 'Homebrew'
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# Install 'openfortivpn'
brew install openfortivpn

or install MacPorts then install openfortivpn:

# Install 'openfortivpn'
sudo port install openfortivpn

A more complete overview can be obtained from repology.

Building and installing from source

For other distros, you'll need to build and install from source:

  1. Install build dependencies.

    • RHEL/CentOS/Fedora: gcc automake autoconf openssl-devel make pkg-config
    • Debian/Ubuntu: gcc automake autoconf libssl-dev make pkg-config
    • Arch Linux: gcc automake autoconf openssl pkg-config
    • Gentoo Linux: net-dialup/ppp pkg-config
    • openSUSE: gcc automake autoconf libopenssl-devel pkg-config
    • macOS (Homebrew): automake autoconf [email protected] pkg-config
    • FreeBSD: automake autoconf libressl pkgconf

    On Linux, if you manage your kernel yourself, ensure to compile those modules:

    CONFIG_PPP=m
    CONFIG_PPP_ASYNC=m
    

    On macOS, install 'Homebrew' to install the build dependencies:

    # Install 'Homebrew'
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    
    # Install Dependencies
    brew install automake autoconf [email protected] pkg-config
    
    # You may need to make this openssl available to compilers and pkg-config
    export LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS"
    export CPPFLAGS="-I/usr/local/opt/openssl/include $CPPFLAGS"
    export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH"
  2. Build and install.

    ./autogen.sh
    ./configure --prefix=/usr/local --sysconfdir=/etc
    make
    sudo make install

    If targeting platforms with pppd < 2.5.0 such as current version of macOS, we suggest you configure with option --enable-legacy-pppd:

    ./autogen.sh
    ./configure --prefix=/usr/local --sysconfdir=/etc --enable-legacy-pppd
    make
    sudo make install

    If you need to specify the openssl location you can set the $PKG_CONFIG_PATH environment variable. For fine-tuning check the available configure arguments with ./configure --help especially when you are cross compiling.

    Finally, install runtime dependency ppp or pppd.

Running as root?

openfortivpn needs elevated privileges at three steps during tunnel set up:

  • when spawning a /usr/sbin/pppd process;
  • when setting IP routes through VPN (when the tunnel is up);
  • when adding nameservers to /etc/resolv.conf (when the tunnel is up).

For these reasons, you need to use sudo openfortivpn. If you need it to be usable by non-sudoer users, you might consider adding an entry in /etc/sudoers or a file under /etc/sudoers.d.

For example:

visudo -f /etc/sudoers.d/openfortivpn
Cmnd_Alias  OPENFORTIVPN = /usr/bin/openfortivpn

%adm       ALL = (ALL) OPENFORTIVPN

Adapt the above example by changing the openfortivpn path or choosing a group different from adm - such as a dedicated openfortivpn group.

Warning: Make sure only trusted users can run openfortivpn as root! As described in #54, a malicious user could use --pppd-plugin and --pppd-log options to divert the program's behaviour.

SSO/SAML/2FA

In some cases, the server may require the VPN client to load and interact with a web page containing JavaScript. Depending on the complexity of the web page, interpreting the web page might be beyond the reach of a command line program such as openfortivpn.

In such cases, you may use an external program spawning a full-fledged web browser such as openfortivpn-webview to authenticate and retrieve a session cookie. This cookie can be fed to openfortivpn using option --cookie-on-stdin. Obviously, such a solution requires a graphic session.

Contributing

Feel free to make pull requests!

C coding style should follow the Linux kernel coding style.

openfortivpn's People

Contributors

aaronjg avatar adrienverge avatar barracuda156 avatar cheese1 avatar dependabot[bot] avatar dimitripapadopoulos avatar dsg22 avatar ehaupt avatar emelenas avatar floppym avatar gbon121 avatar gm-vm avatar lkundrak avatar lucize avatar luz avatar m33m33 avatar mabin-j avatar martinetd avatar mnencia avatar mrbaseman avatar mss avatar nbirnel avatar nehaljwani avatar nknotts avatar ryzhovau avatar schlatterbeck avatar simonkagstrom avatar simontegelid avatar sliim avatar voda 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

openfortivpn's Issues

GCD semaphores might be unsafe when used in signal handlers

Openfortivpn currently uses GCD (Grand Central Dispatch) semaphores on OS-X. This is done to work around the fact the that OS-X doesn’t support unnamed posix semaphores. I ran into the same problem while working on another project and while looking for workarounds I found multiple solutions suggesting substituting posix semaphores with GCD semaphores, but I was not able to find any documentation specifying if GCD semaphores are async-signal safe.

I did some further digging and found the source for GCD. As you can see here and here, GCD uses mach/semaphore.h internally. Unfortunately, the documentation for mach/semaphore.h suggest that they are not async-signal safe.

Semaphores can be used any place where mutexes can occur. This precludes their use in interrupt handlers or within the context of the scheduler, and makes it strongly discouraged in the VM system.

If this is correct, it is properly a bad idea to use GCD semaphores. The currently solution might work most of the time, but specific timing might cause it to fail. Here is more info on Async-Signal Safety.

Here is another discussion about the same problem in OpenJDK. They suggest using BSD kqueue/kevent.

In the other project I was working on we ended up using pipes, similar to this. This should work on all posix compliant systems, unlike unnamed semaphores which are an optional part of the posix standard.

Received bad header from gateway

Hi,

When I try openfortivpn against my companies new VPN, I get:
ERROR: Received bad header from gateway: 6e2e 686f 7374

Looking at the code, it looks like I am getting a magic of 0x686f instead of 0x5050. Can I ask how you determined that it should be 0x5050 and how you figured out that total=size+6?

Thanks,

John

Run as system daemon

What's the best practice in order to run openfortivpn as a system daemon, e.g. as a systemd unit? I'm particularly concerned about automatic reconnection in case of connection loss.

configure option --sysconfdir is not honored during runtime

the configure option --sysconfdir is honored during installation and the config file is correctly placed there. However, when running openfortivpn without command line options it searches the config in the hard coded place /etc/openfortivpn/config, even when --prefix or --sysconfdir at configure time points somewhere else. This could be improved by passing sysconfdir somehow as a macro to the preprocessor. I have been playing around for a while with autoconf, but didn't find a robust solution, yet.

DNS servers not added to resolv.conf

Here is another relevant difference between openfortivpn and the proprietary client.

When /etc/resolv.conf is already populated the proprietary client adds the VPN nameservers one the top of the file, removing them when quitting, as expected. This doesn't happen with openfortivpn, that doesn't touch /etc/resolv.conf if something is already in there.

pppd_write thread after of login

I try connect to Fortinet 3600c and with openfortinet i received this:

DEBUG: Loaded config file "/etc/openfortivpn/config".
DEBUG: Config host = "xxx.xxx.xxx.xxx"
DEBUG: Config port = "443"
DEBUG: Config username = "USER"
DEBUG: Config password = "********"
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
INFO: Connected to gateway.
INFO: Authenticated.
DEBUG: Cookie: SVPNCOOKIE=LjCzS7t/yW9m3VhczWY0Rz9QnpYKlGla25prgY%0ao6ppc/Jeem4r1H3X+EYkiOZVt7eALp8jAfaLfvAUJWaZmyhp6gDqcbGzpLToPHrHBy/gEfuCoPCtko1lluRG/zeI`�
INFO: Remote gateway has allocated a VPN.
DEBUG: pppd_read_thread
DEBUG: ssl_read_thread
DEBUG: if_config thread
DEBUG: ssl_write_thread
DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 04 00 05 06 71 21 49 87
DEBUG: pppd_write thread
ERROR: Received bad header from gateway: 4854 5450 2f31
WARN: Looks like a HTTP 403.
INFO: Cancelling threads...
DEBUG: Waiting for pppd to exit...
INFO: Terminated pppd.
INFO: Logged out.
INFO: Closed connection to gateway.

With the windows client of fortinet I can connect without problem, with openfortivpn , auth is ok, I see that problem can be pppd program, I don't sure, you have some idea?

greetings.

Buffer overflow when connecting

I am running into a buffer overflow when connecting to a (out of my control) VPN server. I traced it down to the function parse_config which does not properly check the boundaries when trying to read the value of the "text6" input field.

For the server I am connecting to this field is empty so naturally the search for '/' picks up the next closing html tag which results in the buffer overflow when copying the data.

This is what is returned by the server for /remote/fortisslvpn:

<HTML>

<HEAD>

<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<META http-equiv="Pragma" content="no-cache">
<META http-equiv="cache-control" content="no-cache">
<META http-equiv="cache-control" content="must-revalidate">
<link href="/sslvpn/css/sslvpn.css" rel="stylesheet" type="text/css">

<TITLE>Fortinet SSL-VPN Client Version 1.0</TITLE>

<!-- SSL-VPN protocol version:
embed.FGTversion = 1;
fortisslvpn.FGTversion = 1
-->

</HEAD>
<BODY class=main>
<form name="fortisslvpn">
<input type="hidden" NAME="text6" VALUE="">
<input type="hidden" NAME="text3" value="server.name.is.here:443">
<input type="hidden" NAME="text7" value="0">

It is possible to connect using forticlient. Let me know if I can provide more information. I do not have access to or more information on the server.

garbage is appended to /etc/resolv.conf

I just wanted to update the openfortivpn package for NixOS to the latest version. Everything seemed to be working fine and I can in fact connect to our vpn. The problem is that after disconnecting VPN some garbage is being appended to /etc/resolv.conf:

^S^]AddTrust Exte<91>

As you can see in my package update PR for openfortivpn the best guess from some other contributor is that it might be some pointer corruption.

How can I provide useful information to figure out what is going on ?

Error : (No cookie given)

Hello when I try to connect to the gateway, I only get the error above.
openfortivpn -vvv -u XXXX --trusted-cert XXXX host:port
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
INFO: Connected to gateway.
ERROR: Could not authenticate to gateway (No cookie given).
INFO: Closed connection to gateway.

[Feature request] Add an option to use dnsmasq instead of resolv.conf

Currently OpenFortiVPN adds nameservers directly to resolv.conf. It breaks the name server order (as they are added at the top) and so some name resolutions in my case (using dnsmasq).

I solved it by using the network-manager-fortisslvpn plugin that use dnsmasq, but it could be a good idea to add a command line option to be able to use dnsmasq to add nameservers, instead of adding them to resolv.conf directly, in openfortivpn directly for those who prefer to use the command line program.

Restrict SSL options/ciphers to secure defaults

Hi,

ssl_connect in tunnel.c[1] probably should probably be using
SSL_CTX_set_options(tunnel->ssl_context, SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION)
("my" server already refuses SSLv3, wasn't able to check if it'd accept compression, but it's likely safer to disable anyway)

We also want to limit the cipher lists, the openssl wiki[2] gives
SSL_set_cipher_list(tunnel->ssl_handle, "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4")

This one is pretty important given "my" server supports very weak ciphers like RC4-MD5 and RC4-SHA, so a man-in-the-middle could downgrade our cipher unless we're strict about it.

For reference, here is a full list of ciphers my server seems to support (obtained looping through available ciphers as described here[3]):

    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Cipher    : ECDHE-RSA-AES256-SHA384
    Cipher    : ECDHE-RSA-AES256-SHA
    Cipher    : DHE-RSA-AES256-GCM-SHA384
    Cipher    : DHE-RSA-AES256-SHA256
    Cipher    : DHE-RSA-AES256-SHA
    Cipher    : DHE-RSA-CAMELLIA256-SHA
    Cipher    : AES256-GCM-SHA384
    Cipher    : AES256-SHA256
    Cipher    : AES256-SHA
    Cipher    : CAMELLIA256-SHA
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Cipher    : ECDHE-RSA-AES128-SHA256
    Cipher    : ECDHE-RSA-AES128-SHA
    Cipher    : DHE-RSA-AES128-GCM-SHA256
    Cipher    : DHE-RSA-AES128-SHA256
    Cipher    : DHE-RSA-AES128-SHA
    Cipher    : DHE-RSA-SEED-SHA
    Cipher    : DHE-RSA-CAMELLIA128-SHA
    Cipher    : AES128-GCM-SHA256
    Cipher    : AES128-SHA256
    Cipher    : AES128-SHA
    Cipher    : SEED-SHA
    Cipher    : CAMELLIA128-SHA
    Cipher    : ECDHE-RSA-RC4-SHA
    Cipher    : RC4-SHA
    Cipher    : RC4-MD5
    Cipher    : ECDHE-RSA-DES-CBC3-SHA
    Cipher    : EDH-RSA-DES-CBC3-SHA
    Cipher    : DES-CBC3-SHA

I'm not sure all servers are as up to date as mine so don't know what defaults are really safe, I'd say the example here is good enough, but haven't looked at openfortivpn's configuration to see if it'd be easy to make configurable :)

[1] https://github.com/adrienverge/openfortivpn/blob/master/src/tunnel.c#L323
[2] https://wiki.openssl.org/index.php/SSL/TLS_Client
[3] http://superuser.com/questions/109213/how-do-i-list-the-ssl-tls-cipher-suites-a-particular-website-offers

On slow connections, VPN connection stop working after few seconds

While it's working perfectly fine with good broadband connection, I've noticed that when used on a slow connection, in my case ReachDSL2 with 2Mbits/sec download and 400Kbits/sec upload, it stops working after few seconds:

PING 192.168.2.49 56(84) bytes of data.
64 bytes from 192.168.2.49: icmp_seq=1 ttl=60 time=48.5 ms
64 bytes from 192.168.2.49: icmp_seq=2 ttl=60 time=49.4 ms
64 bytes from 192.168.2.49: icmp_seq=3 ttl=60 time=50.9 ms
64 bytes from 192.168.2.49: icmp_seq=4 ttl=60 time=51.1 ms
64 bytes from 192.168.2.49: icmp_seq=5 ttl=60 time=48.3 ms
64 bytes from 192.168.2.49: icmp_seq=6 ttl=60 time=51.0 ms
64 bytes from 192.168.2.49: icmp_seq=7 ttl=60 time=52.7 ms
64 bytes from 192.168.2.49: icmp_seq=8 ttl=60 time=49.5 ms
64 bytes from 192.168.2.49: icmp_seq=9 ttl=60 time=49.7 ms
64 bytes from 192.168.2.49: icmp_seq=10 ttl=60 time=50.1 ms
64 bytes from 192.168.2.49: icmp_seq=11 ttl=60 time=51.6 ms
64 bytes from 192.168.2.49: icmp_seq=12 ttl=60 time=52.3 ms
64 bytes from 192.168.2.49: icmp_seq=13 ttl=60 time=48.8 ms
64 bytes from 192.168.2.49: icmp_seq=14 ttl=60 time=53.2 ms
64 bytes from 192.168.2.49: icmp_seq=15 ttl=60 time=51.9 ms
64 bytes from 192.168.2.49: icmp_seq=16 ttl=60 time=50.7 ms
64 bytes from 192.168.2.49: icmp_seq=17 ttl=60 time=50.9 ms
64 bytes from 192.168.2.49: icmp_seq=18 ttl=60 time=57.8 ms
64 bytes from 192.168.2.49: icmp_seq=19 ttl=60 time=117 ms
64 bytes from 192.168.2.49: icmp_seq=20 ttl=60 time=50.1 ms
64 bytes from 192.168.2.49: icmp_seq=21 ttl=60 time=53.5 ms
64 bytes from 192.168.2.49: icmp_seq=22 ttl=60 time=50.1 ms
64 bytes from 192.168.2.49: icmp_seq=23 ttl=60 time=52.0 ms
64 bytes from 192.168.2.49: icmp_seq=24 ttl=60 time=48.0 ms
64 bytes from 192.168.2.49: icmp_seq=25 ttl=60 time=49.4 ms
64 bytes from 192.168.2.49: icmp_seq=26 ttl=60 time=51.2 ms
64 bytes from 192.168.2.49: icmp_seq=27 ttl=60 time=73.6 ms
=> No ping answer after that line

I think it's matter of ppp settings, but I don't know what to change to fix this. I'm using default /etc/ppp/options file from Ubuntu 16.04.1
openfortivpn-slowconnection-issue.zip
(find a copy attached).

The attached ZIP contains the debug log and the ppp options settings.

Routes not correctly set

Now that #18 is fixed openfortivpn basically works for me, but I found that the the routing table is not configured correctly, while it is when using the proprietary client.

The proprietary client adds some specific routes for some networks, while openfortivpn just adds a default route, breaking my Internet connection (I already have a working default route that should not be changed).

As a workaround it is possible to use --no-routes and then add the relevant routes manually.
If you need more information on this issue just let me know. Thank you!

the credentials are passed on the URL, which is very unreliable

hi there.
This is yet another case stressing the importance of library usage.
Click: http.c
username and password are sent "as is", not escaped.
Ergo, if they are URL "unsafe", they will be processed by the server differently than expected.

Reproducing:

  1. add a user to a working server: username="iamneverhome" with password: call&my=home
  2. try connecting using official client - works
  3. try connecting using openfortivpn with correct password. you get auth failure.

Why? The server interprets & as splitter, end of password param and then "my=home" is also treated as param. so for the server, the password is being processed as "call".

I'm sorry I'm swamped with customers and work, but I looked at curl/curl.h, it's a bit ugly, but it exactly addresses these cases - fully. e.g. escaping is done by calling curl_easy_escape().

src/main.c:106: poor choice of local data type ?

[src/main.c:106]: (warning) Storing getchar() return value in char variable and then comparing with EOF.

    char c = getchar();
    if (c == '\n' || c == EOF)

Basic C knowledge, but the return value from getchar should always be
stored in an int, not char.

Connection dies with 'Protocol violation with EOF' after some time

Not sure what to make of it - the tunnel comes online and works for a short time, then dies with these error messages:

DEBUG:  Error reading from SSL connection (Protocol violation with EOF).
INFO:   Cancelling threads...
INFO:   Setting ppp interface down.
INFO:   Restoring routes...
INFO:   Removing VPN nameservers...
DEBUG:  Waiting for pppd to exit...
INFO:   Terminated pppd.
INFO:   Closed connection to gateway.
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Logged out.

Running master from 19. of January 2017 on Mac OS X 10.12.2 (16C68).

What further information can I give to help you debug this problem?

Error reading from SSL connection (Protocol violation with EOF).

Hello,

a ppp0 Interface exists for some seconds, but does not get an IP.
The Debug log shows several Error reading from SSL connection (Protocol violation with EOF).

openfortivpn version: 1.2.0

openfortivpn --no-routes --no-dns -vvv &
DEBUG: Loaded config file "/etc/openfortivpn/config".
DEBUG: Config host = "vpn.[...]"
DEBUG: Config realm = ""
DEBUG: Config port = "443"
DEBUG: Config username = "[...]"
DEBUG: Config password = "********"
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
INFO: Connected to gateway.
INFO: Authenticated.
DEBUG: Cookie: SVPNCOOKIE=[...]
DEBUG: Error reading from SSL connection (Protocol violation with EOF).
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
INFO: Remote gateway has allocated a VPN.
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
DEBUG: Error reading from SSL connection (Protocol violation with EOF).
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
DEBUG: pppd_read_thread
DEBUG: ssl_write_thread
DEBUG: if_config thread
DEBUG: ssl_read_thread
DEBUG: pppd_write thread
DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 05 4a 05 06 ba 9a d0 9b

DEBUG: Error reading from SSL connection (Protocol violation with EOF).
INFO: Cancelling threads...
DEBUG: Waiting for pppd to exit...
INFO: Terminated pppd.
INFO: Closed connection to gateway.
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
INFO: Logged out.

Redistribution of GPL-ed binaries linked with OpenSSL is not permitted

There's a well known clash between the licenses (OpenSSL adds an "additional restriction" which is specifically not allowed by GPL). Therefore the license doesn't allow anyone to redistribute the resulting binaries (since a e.g. a Linux distro shipping both is technically a derived work of the package).

I'd be very thankful if this could be solved and I could distribute the code in Fedora. One obvious solution would be to port it to some other library that does encryption; be it NSS or GNU TLS. Another solution is to add an exception to the openfortivpn license which would allow it to be linked with OpenSSL. I'd prefer the latter as the former takes some non-trivial effort.

See this document for analysis; the possible solutions and links to examples how it has been dealt with:
https://people.gnome.org/~markmc/openssl-and-the-gpl.html

Thank you
Lubo

Presented routes are not implemented

Hi!

My gateway presents some routes to the client, and these routes are not implemented when connecting.

For example, if I connect to my gateway by using proprietary Forticlient for Linux, I got following VPN releted routes:

Destino         Pasarela        Genmask         Indic Métric Ref    Uso Interfaz
0.0.0.0         172.16.34.1     0.0.0.0         UG    0      0        0 wlan0
172.16.34.0     0.0.0.0         255.255.255.0   U     9      0        0 wlan0
172.29.0.0      172.29.1.67     255.255.0.0     UG    0      0        0 ppp0
172.29.1.64     172.29.1.67     255.255.255.224 UG    0      0        0 ppp0
192.168.4.0     172.29.1.67     255.255.255.0   UG    0      0        0 ppp0
192.168.8.0     172.29.1.67     255.255.255.0   UG    0      0        0 ppp0
192.168.9.0     172.29.1.67     255.255.255.0   UG    0      0        0 ppp0
my-gateway-IP   172.16.34.1     255.255.255.255 UGH   0      0        0 wlan0

But by using openfortivpn my routes were:

Destino         Pasarela        Genmask         Indic Métric Ref    Uso Interfaz
0.0.0.0         0.0.0.0         0.0.0.0         U     0      0        0 ppp0
1.1.1.1         0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
172.16.34.0     0.0.0.0         255.255.255.0   U     9      0        0 wlan0
my-gateway-IP   172.16.34.1     255.255.255.255 UGH   0      0        0 wlan0

ERROR: read: Input/output error

I can not connect with openfortivpn version 1.1.4 built from the master branch under Debian testing. It fails with "ERROR: read: Input/output error":

$ su -c 'openfortivpn vpn.****.net:443 -u cgogolin -v -v -v -v -v -v -v --trusted-cert ***********************************'
Password: 
DEBUG:  Loaded config file "/etc/openfortivpn/config".
VPN account password: 
DEBUG:  Config host = "vpn.****.net"
DEBUG:  Config realm = ""
DEBUG:  Config port = "443"
DEBUG:  Config username = "cgogolin"
DEBUG:  Config password = "********"
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Connected to gateway.
INFO:   Authenticated.
DEBUG:  Cookie: SVPNCOOKIE=****
INFO:   Remote gateway has allocated a VPN.
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
DEBUG:  ssl_read_thread
DEBUG:  ssl_write_thread
DEBUG:  if_config thread
DEBUG:  pppd_read_thread
DEBUG:  pppd_write thread
DEBUG:  gateway ---> pppd (12 bytes)
gtw:    c0 21 01 01 00 0a 05 06 bb c8 89 5b

ERROR:  read: Input/output error
INFO:   Cancelling threads...
DEBUG:  Waiting for pppd to exit...
INFO:   Terminated pppd.
INFO:   Closed connection to gateway.
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Logged out.

User certificate?

Looking at the documentation and code I can not find an option to point at my user certificate. Our Fortinet vpn needs both, server and client certificates.

It would be great if you can add this parameter.

diagnostic message colors invisible in gnome-terminal

I just discovered that OpenFortiVPN actually prints diagnostic messages, not just some gratuitous empty lines! The problem is that these diagnostic messages are hardly visible in gnome-terminal in the standard light system theme. Here is a screenshot.
openfortivpn-in-gnome-terminal

add a way to use openresolv

when openresolv is available, please add a way to use it so that openfortivpn does not overwrite resolv.conf.

what's the purpose of the --sysconfdir flag

Whats the purpose of the --syscondir flag for the configure script ?

I've set it to a folder somewhere but when i run openfortivpn it complains that /etc/openfortivpn/config is not found

Connects but can't reach any hosts - then disconnects

Hi, I've just built the client on a Raspberry Pi 3, and I can connect, auth, and it's pushing the correct DNS servers etc. Routing table looks good (at least to me), but I can't ping nor SSH to any hosts.

After about 2-3 minutes the VPN then disconnects with an Input/Output error. Anyone have any ideas what could be wrong please?

TIA

Version: openfortivpn-1.3.0

Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.110.254 0.0.0.0 UG 202 0 0 eth0
1.1.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
100.78.0.0 10.248.0.2 255.255.0.0 UG 0 0 0 ppp0
172.15.15.0 10.248.0.2 255.255.255.0 UG 0 0 0 ppp0
192.168.0.0 10.248.0.2 255.255.0.0 UG 0 0 0 ppp0
192.168.110.0 0.0.0.0 255.255.255.0 U 202 0 0 eth0
195.244.160.0 10.248.0.2 255.255.224.0 UG 0 0 0 ppp0

INFO: Connected to gateway.
INFO: Authenticated.
INFO: Remote gateway has allocated a VPN.
INFO: Got addresses: [10.248.0.2], ns [192.168.34.250, 192.168.34.251]
INFO: Got addresses: [10.248.0.2], ns [192.168.34.250, 192.168.34.251]
INFO: Interface ppp0 is UP.
INFO: Setting new routes...
INFO: Adding VPN nameservers...
INFO: Tunnel is up and running.
ERROR: read: Input/output error
INFO: Cancelling threads...
INFO: Setting ppp interface down.
INFO: Restoring routes...
INFO: Removing VPN nameservers...
INFO: Terminated pppd.
INFO: Closed connection to gateway.
INFO: Logged out.

pppd_write thread after of login

I try connect to Fortinet 3600c and with openfortinet i received this:

DEBUG: Loaded config file "/etc/openfortivpn/config".
DEBUG: Config host = "xxx.xxx.xxx.xxx"
DEBUG: Config port = "443"
DEBUG: Config username = "USER"
DEBUG: Config password = "********"
DEBUG: Gateway certificate validation failed.
DEBUG: Gateway certificate digest found in white list.
INFO: Connected to gateway.
INFO: Authenticated.
DEBUG: Cookie: SVPNCOOKIE=LjCzS7t/yW9m3VhczWY0Rz9QnpYKlGla25prgY%0ao6ppc/Jeem4r1H3X+EYkiOZVt7eALp8jAfaLfvAUJWaZmyhp6gDqcbGzpLToPHrHBy/gEfuCoPCtko1lluRG/zeI`�
INFO: Remote gateway has allocated a VPN.
DEBUG: pppd_read_thread
DEBUG: ssl_read_thread
DEBUG: if_config thread
DEBUG: ssl_write_thread
DEBUG: pppd ---> gateway (16 bytes)
pppd: c0 21 01 01 00 0e 01 04 04 00 05 06 71 21 49 87
DEBUG: pppd_write thread
ERROR: Received bad header from gateway: 4854 5450 2f31
WARN: Looks like a HTTP 403.
INFO: Cancelling threads...
DEBUG: Waiting for pppd to exit...
INFO: Terminated pppd.
INFO: Logged out.
INFO: Closed connection to gateway.

With the windows client of fortinet I can connect without problem, with openfortivpn , auth is ok, I see that problem can be pppd program, I don't sure, you have some idea?

greetings.

Closing a vpn tunnel connection

Is there a common way to programmatically close a vpn tunnel using ruby? I know in openconnect you are able to store the pid and kill the process using that pid.

openfortivpn does not work with two-factor token auth

We have a few fortigate firewalls with SSLVPN. One of them has a two-factor authentication configured (the fortigate sends a one-time token, I believe by email which is converted to SMS). Openfortivpn does not manage to establish a connection with this firewall.

sudo openfortivpn <host:port> -u <username> --trusted-cert <hash> -vvvvvvvvvv
WARN:   Bad port in config file: "0".
DEBUG:  Loaded config file "/etc/openfortivpn/config".
VPN account password: 
DEBUG:  Config host = "<host>"
DEBUG:  Config port = "<port>"
DEBUG:  Config username = "<username>"
DEBUG:  Config password = "********"
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Connected to gateway.
ERROR:  Could not authenticate to gateway (No cookie given).
INFO:   Closed connection to gateway.
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Logged out.

The dialogue with the server looks something like:
Request:

/remote/logincheck
username=<username>&credential=<password>&realm=&ajax=1&redir=%2Fremote%2Findex&just_logged_in=1

Response:

HTTP/1.1 200 OK
Date: Fri, 20 Nov 2015 15:36:20 GMT
Set-Cookie:  SVPNCOOKIE=; path=/; expires=Fri, 20-Nov-2015 15:36:20 GMT; secure; httponly;
Set-Cookie: SVPNNETWORKCOOKIE=; path=/remote/network; expires=Fri, 20-Nov-2015 15:36:20 GMT; secure; httponly
Transfer-Encoding: chunked
Content-Type: text/plain
X-Frame-Options: SAMEORIGIN

51    
ret=4,reqid=<integer>,polid=1,grp=<VPN group string>,portal=<VPN group string?>,tokeninfo=<string>

So, SVPNCOOKIE is set to empty, presumably to be set to a correct value after calling whatever should come next with the correct one-time token.

From looking at a capture of the official fortigate client talking to the same gateway, it looks like the OTP submission should look POST to /remote/logincheck with request body like this:

username=<username>&realm=&reqid=<reqid_integer>&polid=<polid_integer>&grp=<VPN group string>&code=<OTP code>&code2=&redir=%2Fremote%2Findex&just_logged_in=1

Allow other options in config file

The config file can contain only some keys but not all of usable commandline parameters.
Please add support of all of the parameters (notably no-dns) as keys in the config file.

error: defined but not used [-Werror=unused-function]

I am attempting to package openfortivpn for Debian. I get these error messages at compile-time:

src/io.c:49:22: error: 'thread_id' defined but not used [-Werror=unused-function]
 static unsigned long thread_id()
                      ^~~~~~~~~
src/io.c:42:13: error: 'lock_callback' defined but not used [-Werror=unused-function]
 static void lock_callback(int mode, int type, char *file, int line)
             ^~~~~~~~~~~~~

It looks like the packaging environment forces unused-function compiler warnings into errors.

execvp: No such file or directory

Who can help?

Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Config username = "seven"
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Config password = "********"
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: One-time password = ""
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Gateway certificate validation failed.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Gateway certificate digest found in white list.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Connected to gateway.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Authenticated.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Cookie: SVPNCOOKIE=Q7XBlrOfasWHAJOp0psE4Mi8F7FRw0CXjcsEovY4+Lm+yXC3D59S1EUVNkjuW0KK%0aPU10Fyz7oevh25rWtueseLR8WUxg02ZCqx6VYn6hfTMztv/0Ubmm4roJ81dEO5CA%0aDOD/8hrw5pIlHxSyPy/6pdxffFLm9PveaPNfxijOsZA=%0a
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Remote gateway has allocated a VPN.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Gateway certificate validation failed.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Gateway certificate digest found in white list.
Jan  5 02:39:19 rt-g2 openfortivpn[25737]: execvp: No such file or directory
Jan  5 02:39:19 rt-g2 openfortivpn[25737]: Closed connection to gateway.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: pppd_read_thread
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: ssl_read_thread
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: ssl_write_thread
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: if_config thread
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: gateway ---> pppd (12 bytes)
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: gtw:    c0 21 01 01 00 0a 05 06 31 9d d2 4f
Jan  5 02:39:19 rt-g2 openfortivpn[25737]: Gateway certificate validation failed.
Jan  5 02:39:19 rt-g2 openfortivpn[25737]: Gateway certificate digest found in white list.
Jan  5 02:39:19 rt-g2 openfortivpn[25737]: Logged out.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: read: Input/output error
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Cancelling threads...
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Waiting for pppd to exit...
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Terminated pppd.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Closed connection to gateway.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Gateway certificate validation failed.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Gateway certificate digest found in white list.
Jan  5 02:39:19 rt-g2 openfortivpn[25736]: Logged out.

Syslog support

I have submitted a pull-request (#65) for adding syslog-support for the log messages.
My use-case is to run openfortivpn non-interactively on a small openwrt-based router.
I'm using the patch in the pull-request successfully for several months now, so maybe you consider to accept the patch? Or do I need to add something to make you reconsider?

I can rebase the patch to the latest head commit if needed.

Ralf

Max number of split route

Hi in my environment I've 96 different route to add to administrative client
the max number of route in openfortivpn is "#define MAX_SPLIT_ROUTES 32"

New release

Hello,

could you be so kind and release new version (1.2.1) with two factor enhancement (already in git)? Reason for this is to push 2Factor auth to distributions (Fedora, Ubuntu and so).

Thank you.

Received bad header from gateway

Hi!

I am trying to connect (mygateway is https://my.gateway.com.br:10443):

sudo /usr/bin/openfortivpn my.gateway.com.br:10443 -u marcelo --no-routes --no-dns --trusted-cert c755c435e2ec1221dea85847c190f9b9200013780bf82cefb25b6074562df2cd
VPN account password:
INFO: Connected to gateway.
INFO: Authenticated.
INFO: Remote gateway has allocated a VPN.
ERROR: Received bad header from gateway:
(hex) 48 54 54 50 2f 31 2e 31 20 34 30 33 20 46 6f 72 62 69 64 64 65 6e 0d 0a 44 61 74 65 3a 20 53 61 74 2c 20 30 33 20 4f 63 74 20 32 30 31 35 20 31 33 3a 30 31 3a 32 35 20 47 4d 54 0d 0a 53 65 74 2d 43 6f 6f 6b 69 65 3a 20 20 53 56 50 4e 43 4f 4f 4b 49 45 3d 3b 20 70 61 74 68 3d 2f 3b 20 65 78 70 69 72 65 73 3d 53 61 74 2c 20 30 33 2d 4f 63 74 2d 32 30 31 35 20 31 33 3a 30 31 3a 32 35 20 47 4d 54 3b 20 73 65 63 75 72 65 3b 20 68 74 74 70 6f 6e 6c 79 3b 0d 0a 53 65 74 2d 43 6f 6f 6b 69 65 3a 20 53 56 50 4e 4e 45 54 57 4f 52 4b 43 4f 4f 4b 49 45 3d 3b 20 70 61 74 68 3d 2f 72 65 6d 6f 74 65 2f 6e 65 74 77 6f 72 6b 3b 20 65 78 70 69 72 65 73 3d 53 61 74 2c 20 30 33 2d 4f 63 74 2d 32 30 31 35 20 31 33 3a 30 31 3a 32 35 20 47 4d 54 3b 20 73 65 63 75 72 65 3b 20 68 74

(raw) HTTP/1.1 403 Forbidden.
Date: Sat, 03 Oct 2015 13:01:25 GMT.
Set-Cookie: SVPNCOOKIE=; path=/; expires=Sat, 03-Oct-2015 13:01:25 GMT; secure; httponly;.
Set-Cookie: SVPNNETWORKCOOKIE=; path=/remote/network; expires=Sat, 03-Oct-2015 13:01:25 GMT; secure; h
INFO: Cancelling threads...
INFO: Terminated pppd.
INFO: Closed connection to gateway.
INFO: Logged out.

Thanks

Can not connect using FortiToken

Hi! First of all thanks for this implementation of a fortisslvpn module, which just feels much better than using the proprietary client.

Using version 1.1.3, unfortunately, if my account within the fortigate is associated with a FortiToken which is our company standard, I just get this error:

INFO:   Connected to gateway.
ERROR:  Could not authenticate to gateway (No cookie given).
INFO:   Closed connection to gateway.

If I release the association with a fortitoken, it works. I'm a bit irritated now, as some pull requests imply that there should be now some support for "two-factor authentication", but I don't know, if that should mean FortiTokens are supported yet.

Unfortunately I'm not enough developer to find the issue myself, but I'm happy to help with debugging, if someone tells me what I can do.

Thanks!

add pppd options "call" or "file"

Sometimes additional pppd options are needed, e.g. to set connection specific routes when the link goes up.

If openfortivpn could pass a "call " (or "file ") option to pppd, any additional pppd-options could be specified in that file.

Two-factor authentication

One of my customers has recently switched to two-factor auth using a security-token.
When connecting with the official client it asks for a second password after the first.
With openfortivpn I'm getting
Fri Dec 16 12:08:18 2016 daemon.err openfortivpn[7389]: Could not authenticate to gateway (Bad HTTP response code).
(this message with my patch to allow log-output to syslog, see open pull request #65)
Are you interested in making 2-factor auth work and help me debug & patch openfortivpn?
I'd guess my first step would be to print the http response in the step that fails above...

Ralf

set up routes correctly when ppp0 interface is already there

as discussed in pull request #90 which implemented that a new ppp device is used when ppp0 is already there, I have noticed a problem when the vpn pushes a new default route over the new ppp1 interface.
In that particular case adding the gateway route fails in ipv4_set_default_routes with the following debug output:

DEBUG: ip route add to A.B.C.D/255.255.255.255 via 0.0.0.0 dev ppp0
WARN: Could not set route to tunnel gateway (Invalid argument).

Adding a host route over ppp0 before starting openvpn makes the tunnel work. The above warning still appears then, but the tunnel works. Comparing the routing entries I found that in this case the flags are sligtly different. Instead of
gtw_rt->rt_flags |= RTF_GATEWAY;
one would have to put:
gtw_rt->rt_flags |= RTF_HOST;
However, when I try to open a vpn connection to another gateway, which does not push a default route, the code is needed as it is. This is in the early stage, before the routes etc. are received, so I'm not sure how to handle this decision. Maybe we should add an option to the config file (something like is-gateway or host-route or additional-flags...) which is used here and allows us to control the setup of the routes. Any suggestions? I'm willing to implement and test this, but @adrienverge, I would like to have your opinion which path I should follow.

Tag a new release

Can you please tag a new release so I can use it to build a Gentoo package? The current one is quite old (and doesn't include the fix I need ;-))

Being able to connect with a --cookie parameter

It would be nice if you are able to connect with a --cookie parameter.

I'm working on a wrapper gui for openfortivpn which does the fortinet http auth to catch the SVPNCOOKIE, it would be nice if openfortivpn could create a connection if it receives the cookie

then in ps -ef the password wouldn't show up, and the password wouldn't be exposed in a openfortivpn config file

Ofcourse its possible to specify the password through an interactive prompt, but this is a bit complex to handle when you spawn openfortivpn in a background process

otp commandline parameter

Hello,

-o or --opt= switch does nothing. Output follows:

openfortivpn <gateway-ip> -u user -p password --opt=123456
INFO: Connected to gateway.
2factor authentication token:

We are using version 1.3.0

"--ppd-plugin" and "--ppd-log" parameters may be a security risk when running through sudo

When execution of the openfortivpn executable is granted to unprivileged users the way the example on the project frontpage shows, the --ppp-plugin and --ppd-log arguments are passed directly to pppd as plugin, respective logfile.

As pppd in this case will be executed as root, plugin allows to load a mailicious user controlled plugin from an arbitrary location as root. This could probably be mitigated by only allowing plugin names which don't contain a slash, therfore limiting loading plugins only from the /usr/lib/pppd/[version] directory.

logfile allows to open (or create) an aribitray file as root and append log output to it. pppd when not invoked as root opens the log file as the original user, but in this case it's already invoked as root thorugh sudo.

At the very least the instructions on the front page should be changed not to allow direct execution of the openfortivpn binary but of a wrapper script that doesn't take potentially insecure user arguments.

"could not set route to tunnel gw" error in Ubuntu 16.04

Hello,

I recently upgraded to Ubuntu 16.04. Since that upgrade, I cannot connect using openfortivpn because:

DEBUG:  ip route add to 0.0.0.0/106.127.0.0 dev ppp0
WARN:   Could not set route to tunnel gateway (Address family not supported by protocol).

May be linux version (4.4.0)?

Could you help us?

Thanks!

Is it possible to use more then one vpn at the same time?

Hello,

i would like to use the programm to have multible vpn's active at the same time. I can call the programm more then once. But have problem with useing all vpn's the same ppp interface, or there are problems with the routing.

How can i use it more then for one vpn at the same time?

Best Regards

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.