Quantcast
Channel: Mike Walton's Technical Journal » Mike Walton
Viewing all articles
Browse latest Browse all 7

Guide: NGINX Reverse Proxy for Lync 2013

$
0
0

Introduction

Setting up a reverse proxy for an on premises Lync 2013 (aka Skype for Business) environment is fairly straightforward but the technical details are not very well documented, and there is very little out there for the excellent (and my favourite) web server and reverse proxy, nginx.

There are plenty of guides that talk about ISS APR, Apache or other products and few outline the required features of the proxy itself, namely HTTP Proxy 1.1 support, the keepalive parameters and proxy buffers.

This guide’s focus is on the reverse proxy component of the Lync 2013 architecture, you need to make sure that all other architecture requirements are met including DNS records. For help with that see Jack Stromberg’s excellent guide.

Without too much fuss, here is the reverse proxy configuration we are using in production with Lync 2013, it runs on Ubuntu 14.04 and nginx 1.8.0 but will work on most standard nginx environments. This configuration enables remote meeting and mobile application (both iOS and Android).

 

Nginx Configuration (/etc/nginx/sites-enabled/webext.yourdomain.com.conf)

Change yourdomain.com to your public domain.


# =====================================================
# LYNC 2013 Reverse Proxy
# MW 2015
# =====================================================

upstream lync_backend {
	server your-lync-server.DOMAIN.local:4443;
	keepalive 180;
}

server {
	listen 443;
	server_name webext.yourdomain.com lyncdiscover.yourdomain.com dialin.yourdomain.com meet.yourdomain.com;

	# SSL settings
	ssl on;
	
	# use strong protocols and ciphers with acceptable fallback
	ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
	ssl_session_cache shared:SSL:10m;
	ssl_prefer_server_ciphers on;

	# ssl certificate chain and private key
	ssl_certificate /etc/ssl/certs/webext.yourdomain.com_BUNDLED.pem;
	ssl_certificate_key /etc/ssl/private/webext.yourdomain.com.key;

	error_log /var/www/webext.yourdomain.com_error_log warn;

	root /var/www/webext.yourdomain.com;

	# reverse proxy to Lync with HTTP Proxy 1.1
	location / {
	
		# reset connection to 1.1
		proxy_http_version 	1.1;
		proxy_set_header 	Connection "";
		
		# buffers
		proxy_buffering 	on;
		proxy_buffers		128 4k;
		
		# headers
		proxy_set_header	Host $host;
		proxy_set_header	X-Real-IP $remote_addr;
		proxy_set_header	X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header	X-Forwarded-Proto $scheme;

		# proxy it to lync!
		proxy_pass 		https://lync_backend;
		proxy_redirect 		default;
	}
}

# redirect port 80 traffic to 443 without passing it to Lync backend
server {
	listen 80;
	server_name webext.yourdomain.com lyncdiscover.yourdomain.com dialin.yourdomain.com meet.yourdomain.com;

	return 301 https://$host$request_uri;
}

Nginx Configuration (/etc/nginx/nginx.conf)


# =====================================================
# NGINX Config w/ compression and SSL tweaks
# MW 2015
# =====================================================
user www-data;

error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

worker_rlimit_nofile 8192;

events {
    worker_connections 4096;
    # Accept as many connections as possible.
    multi_accept on;
}

http {
    # MIME types.
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Default log and error files.
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # Use sendfile() syscall to speed up I/O operations and speed up static file serving.
    sendfile on;

    # Timeouts.
    client_body_timeout 60;
    client_header_timeout 60;
    keepalive_timeout 10 10;
    send_timeout 60;

    # Reset lingering timed out connections. Deflect DDoS.
    reset_timedout_connection on;

    # Body size.
    client_max_body_size 10m;

    # TCP options.
    tcp_nodelay on;
    ## Optimization of socket handling when using sendfile.
    tcp_nopush on;

    # Compression.
    gzip on;
    gzip_buffers 16 8k;
    gzip_comp_level 1;
    gzip_http_version 1.1;
    gzip_min_length 10;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/x-icon application/vnd.ms-fontobject font/opentype application/x-font-ttf;
    gzip_vary on;
    gzip_proxied any; # Compression for all requests.
    gzip_disable msie6;

    # Hide the Nginx version number.
    server_tokens off;

    # SSL Settings
    ssl_session_cache shared:SSL:10m;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/nginx/dh_param.pem;
    
    # use strong protocols and ciphers with acceptable fallback
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
    ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";    

    # Enable OCSP stapling. A better way to revocate server certificates.
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout 10s;

    # security headers
    add_header Strict-Transport-Security max-age=63072000;
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

    # indexes
    index index.html;

    # Include all vhosts.
    include /etc/nginx/sites-enabled/*;
}

 

Generate Diffie-Hellman parameters for Forward Secrecy (/etc/nginx/dh_param.pem)

Execute the following in your terminal:
openssl dhparam -out /etc/nginx/dh_param.pem 2048

 

Restart nginx

Execute the following in your terminal:
nginx -s reload

 

Test Lync 2013 Remote Authentication

Navigate to the following in your browser from outside your network (change yourdomain.com to your public domain):
https://webext.yourdomain.com/WebTicket/WebTicketService.svc

Enter your credentials when prompted:

Authentication Prompt
image-179

If all is working you should see something like this:

WebTicketService Success
image-180

If not, you’ll likely get a HTTP 401. Check that you have “Negotiate” authentication enabled in your IIS “Lync Server External Web Site” (see below).

 

Enabling IIS Negotiate Authentication

  1. On your Lync Server, open IIS Manager.
  2. Click the “Lync Server External Web Site”
  3. In the main panel, double click the “Authentication” icon.IIS Step 1
  4. Click “Windows Authentication”, then click “Providers…” from the “Actions” panel.
  5. From the “Available Providers” drop down, select “Negotiate” and click “Add”.
  6. Move Negotiate to the top of the provider list using the “Move Up” button.
    IIS Step 2
    image-181

 

Thoughts?

Please comment below if this worked for you, or if you have some improvements on this configuration and I’ll update this post. I’d love to hear from you if you’re using nginx with Lync 2013!

The post Guide: NGINX Reverse Proxy for Lync 2013 appeared first on Mike Walton's Technical Journal.


Viewing all articles
Browse latest Browse all 7

Trending Articles