Epic is one of the most important software providers in the healthcare segment of the industry today. Given government mandates and support for Electronic Medical Records over the next decade, the presence of Epic at most hospital and clinical facilities will be essential to adhering to regulatory mandates, increasing the overall efficiency and effectiveness of health care delivery and ensuring that patient history can be rapidly shared between healthcare providers.

As doctors and other clinical staff are increasingly mobile, it is essential that access to patient information can follow from practice to hospital to remote clinic. Epic is the leading provider in the Electronic Medical Records space and ensures that patient information can be reliably accessed anywhere.

We have a happy customer that is willing to provide some of the details of his deployment of Epic Hyperspace. One of the very cool aspects of this deployment is the fact that they used the F5 power of iRules to track the hospital or medical center from which the user is connected.  This is important for auditing and (potentially) an internal chargeback mechanism and demonstrates the power of the F5 full proxy architecture. I have to admit that cracking a *ucs to document details of the deployment is not always ideal.  As always, please feel free to reach out to me with any details on our joint solution.

 

clip_image002

Figure 1: Primary Site 2-8900 LTM Devices, Secondary Site 1 8900 LTM

Setup and Configuration

Platform

Software Version

Products

BIG-IP 8900 x 2

10.2

LTM

For networking setup and configuration of user traffic the 2 10GB interfaces were configured on the F5 devices. We configured a trunk for the two 10GB interfaces providing a full 20GB pipe for incoming client traffic.

The BIG-IP on which this Epic Hyperspace application is deployed has multiple route domains and other application configurations. We will assume that the user has a working knowledge of the basic BIG-IP networking setup and VLAN configuration.

Configuration of VLANS and Networking

1. Setup and Configuration of Network Trunk on 8900

{

trunk XX-L1-GOPS_CHANNEL19 {

lacp enable

interfaces {

3.1

3.2

}

2. Configure VLAN for Epic Deployment and Associate it with Trunk

vlan VLAN104_EPIC {

tag 104

mac masq 02:01:D7:B7:2A:04

failsafe enable

timeout 30

failsafe failover

trunks tagged XX-L1-GOPS_CHANNEL19

}

route domain 1 {

description "RD1-XXX_EPIC"

vlans VLAN104_EPIC

}

3. Configure Self-IPs

}

self 172.27.104.248%1 {

netmask 255.255.255.0

vlan VLAN104_EPIC

allow default

}

4. Configure Epic Specific Monitors

monitor EPIC_ECP_COMM {

defaults from tcp

timeout 11

dest *:20300

partition P1-XXX_EPIC

}

monitor EPIC_ECP_PROBE {

defaults from tcp

timeout 11

dest *:20110

partition P1-XXX_EPIC

}

monitor EPIC_MOBILE_HAIKU_KHWPEPC001 {

defaults from http

partition P1-XXX_EPIC

recv "Interconnect Service:

RunningStatus\" class=\"running\">Running"

send "GET /interconnect-haiku/default.aspx HTTP/1.1\r\nHost: xxxpepc001.xxx

ealth.com\r\nConnection: Close\r\n\r\n"

}

monitor EPIC_MOBILE_HAIKU_XXXPEPC002 {

defaults from http

partition P1-XXX_EPIC

recv "Interconnect Service:

RunningStatus\" class=\"running\">Running"

send "GET /interconnect-haiku/default.aspx HTTP/1.1\r\nHost: xxxpepc002.ketth

ealth.com\r\nConnection: Close\r\n\r\n"

}

monitor EPIC_MOBILE_INTER_XXXPEPC001 {

defaults from http

partition P1-XXX_EPIC

recv "OLTP Server Status: UP

an>"

send "GET /interconnect-haiku/default.aspx HTTP/1.1\r\nHost: xxxpepc001.xxxth

ealth.com\r\nConnection: Close\r\n\r\n"

}

monitor EPIC_MOBILE_INTER_XXXPEPC002 {

defaults from http

partition P1-XXX_EPIC

recv "OLTP Server Status: UP

an>"

send "GET /interconnect-haiku/default.aspx HTTP/1.1\r\nHost: xxxpepc002.xxxth

ealth.com\r\nConnection: Close\r\n\r\n"

}

monitor EPIC_PRINT_COMM {

defaults from ftp

partition P1-XXX_EPIC

}

monitor EPIC_PRINT_PROBE_FTP {

defaults from tcp

dest *:ftp

partition P1-XXX_EPIC

}

monitor EPIC_TEST_MONITOR {

defaults from tcp

dest *:ms-wbt-server

partition P1-XXX_EPIC

}

monitor test1 {

defaults from tcp

partition P1-XXX_EPIC

recv "220"

send "ftp://xxx.xx.xxx.xxx"

}

monitor test2 {

defaults from tcp

dest *:ftp

partition P1-XXX_EPIC

}

5. Configure SNAT Pools (Note Only Necessary for Larger Configurations Exceeding 64K Simultaneous Connections, SNAT pools in this instance will be used to log the location of the user)

snatpool BK_SNAT_POOL {

members 172.27.104.224%1

}

snatpool DR_SNAT_POOL {

members 172.27.104.126%1

}

snatpool FH_SNAT_POOL {

members 172.27.104.123%1

}

snatpool GM_SNAT_POOL {

members 172.27.104.124%1

}

snatpool GV_SNAT_POOL {

members 172.27.104.130%1

}

snatpool XX_SNAT_EPIC_MOBILE {

members 172.27.104.181%1

snatpool XX_SNAT_POOL {

members 172.27.104.127%1

}

snatpool XX_SNAT_PRINT {

members 172.27.104.231%1

}

snatpool RS_SNAT_POOL {

members 172.27.104.128%1

}

snatpool SH_SNAT_POOL {

members 172.27.104.125%1

}

snatpool SV_SNAT_POOL {

members 172.27.104.129%1

}

snatpool UNKNOWN_SNAT_POOL {

members 172.27.104.118%1

}

}

6. Configure Epic Test Profiles

profile tcp EPIC_TEST_Profile {

defaults from tcp-lan-optimized

idle timeout 7200

7. Add Nodes to Configuration

node 172.27.104.20%1 {

monitor EPIC_ECP_PROBE

screen XXXPX010

}

node 172.27.104.21%1 {

monitor EPIC_ECP_PROBE

screen XXXPX011

}

node 172.27.104.22%1 {

monitor EPIC_ECP_PROBE

screen XXXPX012

}

node 172.27.104.23%1 {

monitor EPIC_ECP_PROBE

screen XXXPX013

}

node 172.27.104.24%1 {

monitor EPIC_ECP_PROBE

screen XXXPX014

}

node 172.27.104.25%1 {

monitor EPIC_ECP_PROBE

screen XXXPX015

}

node 172.27.104.26%1 {

monitor EPIC_ECP_PROBE

screen XXXPX016

}

node 172.27.104.37%1 {

monitor EPIC_ECP_PROBE

screen XXXPX019

}

node 172.27.104.183%1 {

monitor EPIC_ECP_PROBE

screen XXXPX009

}

pool EPIC_ECP_POOL {

lb method member least conn

monitor all EPIC_ECP_COMM

members {

172.27.104.20%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.21%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.22%1:20300 {

monitor EPI }

172.27.104.23%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.24%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.25%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.26%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.37%1:20300 {

monitor EPIC_ECP_COMM

}

172.27.104.183%1:20300 {

monitor EPIC_ECP_COMM

}

}

}

8. Configure Pools

pool EPIC_INT_INTERCONN_POOL1 {

lb method least connC_ECP_COMM

members {

172.27.104.177%1:http {

monitor gateway_icmp

}

172.27.104.178%1:http {

monitor gateway_icmp

}

}

}

pool EPIC_INT_MOBILE_POOL1 {

lb method least conn

members {

172.27.104.169%1:http {

monitor EPIC_MOBILE_HAIKU_XXXPEPC001 and EPIC_MOBILE_INTER_XXXPEPC001

}

172.27.104.170%1:http {

monitor EPIC_MOBILE_HAIKU_XXXPEPC002 and EPIC_MOBILE_INTER_XXXPEPC002

}

}

}

pool EPIC_PRINT_POOL1 {

monitor all EPIC_PRINT_PROBE_FTP

members {

172.27.104.172%1:ftp {}

172.27.104.173%1:ftp {}

172.27.104.174%1:ftp {}

172.27.104.176%1:ftp {}

}

}

pool EPIC_PRINT_POOL2 {

monitor all EPIC_PRINT_PROBE_FTP

members {

172.27.104.155%1:ftp {}

172.27.104.156%1:ftp {}

172.27.104.171%1:ftp {

monitor EPIC_PRINT_PROBE_FTP

}

}

}

pool EPIC_PRINT_POOL3 {

monitor all EPIC_PRINT_PROBE_FTP

members {

172.27.104.171%1:ftp {}

172.27.104.172%1:ftp {}

172.27.104.173%1:ftp {}

172.27.104.174%1:ftp {}

}

}

pool EPIC_TEST_POOL {

lb method member least conn

monitor all EPIC_TEST_MONITOR

members {

172.27.104.202%1:ms-wbt-server {}

172.27.104.206%1:ms-wbt-server {

monitor EPIC_TEST_MONITOR

}

}

}

9. Configure iRule to Identify Client Location and Log User IP Address

rule IRULE-XXX_EPIC_PROD {

# Location Selective SNAT

# CPU impact: Minimal

# Requirement: - Match Client IP to identify Client location & give proper SNAT address

#

# If client and server are on the same IP network,

# invoke SNAT to prevent IP routed triangulation.

when CLIENT_ACCEPTED {

##Start TCP timer

set tcp_start_time "[clock clicks -milliseconds]"

set LB_SRV "[getfield [IP::local_addr] "%" 1]"

set SRC "[getfield [IP::remote_addr] "%" 1]"

if {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.24.0.0/17]} {

use snatpool GM_SNAT_POOL

set location "XXX"

STATS::incr Location_XXXXXXXXXXX

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.24.128.0/17]}

{

use snatpool BK_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.25.0.0/16]} {

use snatpool SH_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.26.0.0/17]} {

use snatpool DR_SNAT_POOL

set location "XX"

STATS::incr Location_Stats Disaster_Recovery_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.27.0.0/16]} {

use snatpool XX_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.28.0.0/16]} {

use snatpool RS_SNAT_POOL

set location "REMOTE"

STATS::incr Location_Stats XXX_Remote_Sites

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.29.0.0/16]} {

use snatpool SV_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.30.0.0/16]} {

use snatpool XX_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.23.0.0/16]} {

use snatpool FH_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXXXX_Hospital

}

else {

use snatpool UNKNOWN_SNAT_POOL

set location "UNKNOWN"

STATS::incr Location_Stats Unknown_Addresses

}

}

when SERVER_CONNECTED {

set RTT "[expr [clock clicks -milliseconds] - $tcp_start_time]"

##End TCP timer

set SRC_NAT "[getfield [IP::local_addr] "%" 1]"

set REAL_SRV "[getfield [IP::server_addr] "%" 1]"

set DEST_PORT "[TCP::server_port]"

##Src-ClientIP, SRC_NAT-SNAT IP, LB_SRV-VIP, REAL_SRV-Node, DEST_PORT-TCP Po

rt, RTT-TCP Timer time

log -noname local0. "PART=P1-KHN_EPIC, LOCATION=$location, SRC=$SRC, SRC_NAT

=$SRC_NAT, LB_SRV=$LB_SRV, REAL_SRV=$REAL_SRV, DEST_PORT=$DEST_PORT, RTT=$RTT ms

,"

}

}

rule IRULE-XXX_EPIC_TEST {

# Location Selective SNAT

# CPU impact: Minimal

# Requirement: - Match Client IP to identify Client location & give proper SNAT address

#

# If client and server are on the same IP network,

# invoke SNAT to prevent IP routed triangulation.

when CLIENT_ACCEPTED {

##Start TCP timer

set tcp_start_time "[clock clicks -milliseconds]"

set LB_SRV "[getfield [IP::local_addr] "%" 1]"

set SRC "[getfield [IP::remote_addr] "%" 1]"

if {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.24.0.0/17]} {

use snatpool GM_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXX_Memorial_Hospital

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.24.128.0/17]}

{

use snatpool BK_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.25.0.0/16]} {

use snatpool SH_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.26.0.0/17]} {

use snatpool DR_SNAT_POOL

set location "DR"

STATS::incr Location_Stats Disaster_Recovery_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.27.0.0/16]} {

use snatpool XX_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.28.0.0/16]} {

use snatpool RS_SNAT_POOL

set location "REMOTE"

STATS::incr Location_Stats KHN_Remote_Sites

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.29.0.0/16]} {

use snatpool SV_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.30.0.0/16]} {

use snatpool GV_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXXX_Medical_Center

}

elseif {[IP::addr [getfield [IP::remote_addr] "%" 1] equals 172.23.0.0/16]} {

use snatpool FH_SNAT_POOL

set location "XXX"

STATS::incr Location_Stats XXXXXXXXX_Hospital

}

else {

use snatpool UNKNOWN_SNAT_POOL

set location "UNKNOWN"

STATS::incr Location_Stats Unknown_Addresses

}

}

when SERVER_CONNECTED {

set RTT "[expr [clock clicks -milliseconds] - $tcp_start_time]"

##End TCP timer

set SRC_NAT "[getfield [IP::local_addr] "%" 1]"

set REAL_SRV "[getfield [IP::server_addr] "%" 1]"

set DEST_PORT "[TCP::server_port]"

##Src-ClientIP, SRC_NAT-SNAT IP, LB_SRV-VIP, REAL_SRV-Node, DEST_PORT-TCP Po

rt, RTT-TCP Timer time

log -noname local0. "PART=P1-KHN_EPIC, LOCATION=$location, SRC=$SRC, SRC_NAT

=$SRC_NAT, LB_SRV=$LB_SRV, REAL_SRV=$REAL_SRV, DEST_PORT=$DEST_PORT, RTT=$RTT ms

,"

}

}

10. Configure Additional Virtual Server

virtual VS_EPIC_ECP_PROD {

mirror enable

snat automap

pool EPIC_ECP_POOL

destination 172.27.104.100%1:20300

ip protocol tcp

rules IRULE-XXX_EPIC_PROD (Note the use of the iRule for logging location: Not necessary for basic deployment)

profiles {

EPIC_ECP_FASTL4 {}

Location_Stats {}

}

vlans VLAN104_EPIC enable

}

11. Configure Virtual Server Epic Interconnection1

virtual VS_EPIC_INT_INTERCONN1 {

snatpool XX_SNAT_EPIC_MOBILE

pool EPIC_INT_INTERCONN_POOL1

destination 172.27.104.185%1:http

ip protocol tcp

profiles fasthttp {}

vlans VLAN104_EPIC enable

}

12. Configure Epic Mobile 1

virtual VS_EPIC_INT_MOBILE1 {

snatpool XX_SNAT_EPIC_MOBILE

pool EPIC_INT_MOBILE_POOL1

destination 172.27.104.180%1:http

ip protocol tcp

profiles fasthttp {}

vlans VLAN104_EPIC enable

}

13. Configure Epic Print Production 1

virtual VS_EPIC_PRINT_PROD1 {

translate service disable

srcport change

snatpool XX_SNAT_PRINT

pool EPIC_PRINT_POOL1

destination 172.27.104.101%1:ftp

ip protocol tcp

profiles {

ftp {}

tcp-lan-optimized {}

}

vlans VLAN104_EPIC enable

}

14. Configure Epic Print Virtual Server

virtual VS_EPIC_PRINT_PROD2 {

translate service disable

srcport change

snatpool XX_SNAT_PRINT

pool EPIC_PRINT_POOL2

destination 172.27.104.102%1:ftp

ip protocol tcp

profiles {

ftp {}

tcp {

clientside

}

tcp-lan-optimized {

serverside

}

}

vlans VLAN104_EPIC enable

}

15. Configure Epic Print Production 3 Virtual Server

virtual VS_EPIC_PRINT_PROD3 {

translate service disable

snatpool XX_SNAT_PRINT

pool EPIC_PRINT_POOL3

destination 172.27.104.103%1:ftp

ip protocol tcp

profiles {

ftp {}

tcp-lan-optimized {}

}

}

16. Configure Virtual Server Epic Test XP

virtual VS_EPIC_TEST_XP {

mirror enable

snat automap

pool EPIC_TEST_POOL

destination 172.27.104.102%1:ms-wbt-server

ip protocol tcp

rules IRULE-XXX_EPIC_TEST

profiles {

EPIC_ECP_FASTL4 {}

Location_Stats {}

}

vlans VLAN104_EPIC enable

}

}

pool EPIC_MOBILE_POOL1 {

members {

204.110.18.241%4:https {

monitor EPIC_MOBILE_XXWPEPC003_Monitor

}

204.110.18.242%4:https {

session user disabled

monitor EPIC_MOBILE_XXWPEPC004_Monitor

}

}

}

17. Configure Epic EXT Mobile 1 Virtual Server

virtual VS_EPIC_EXT_MOBILE1 {

snatpool SNAT_EPIC_MOBILE

pool EPIC_MOBILE_POOL1

destination 204.110.18.247%4:https

ip protocol tcp

profiles fasthttp {}

vlans VLAN555_EDMZ enable

external path cost 20000

VLAN Configuration:

vlans {

VLAN104_EPIC

VLAN105_UNIT1

VLAN106_UNIT2

VLAN10_IDMZ

VLAN112_UNIT1

VLAN116_UNIT2

VLAN555_EDMZ

VLAN98_MANG

peerNet

}