bvstone

Creating a Reverse SSL Proxy Using RPG on the IBM i

Posted:

Creating a Reverse SSL Proxy Using RPG on the IBM i

Update:  Be sure to check out Part 2 of this article for updated source: Creating a Reverse SSL Proxy Using RPG on the IBM i - Part 2

Last night I was contacted by one of my clients.  Apparently their Credit Card Payment process had quit working.  Why?  For the most part it is because they were still on V5R4.

As most know, SSL/TLS has gone through a lot of changes and updates (for the better).  While this is good from a security standpoint, IBM i customers who are on an unsupported version of the OS (sometimes through no fault of their own) are unable to use the new SSL updates and fixes that are available.

The application used by the client is a 3rd party portal-type credit card processing system.  This means that in the credit card payment process control is passed to this 3rd party to handle the bulk of the credit card processing.  During this process there are a couple callbacks that are made to my client's server.  Mainly this is so they know if the transaction went through ok, but also for security.  Unique processing IDs are used as a sort of "fingerprint" for the transaction so both parties know the data they are working with is valid.

Now, back to the issue.  In this case the credit card company had updated their SSL requirements to SHA-2.  This means any communications between their servers and other customers need to use at least SHA-2 algorithm.  So, the back end communications between the credit card company and my client were impossible as they only could install a SHA-1 certificate because of the outdated OS version.

Home-Made Reverse Proxy to the Rescue

Having worked with reverse proxies before I thought it may be possible for me to set up my V7R3 machine which runs our BVSTools website (with an SSL option) to be a proxy between the credit card processing company and my client.

At first I started looking into a reverse proxy using the Apache server on the IBM i, but noticed that when SSL is used, it becomes a lot more complicated than when it's just plain HTTP traffic.  

I then realized I had all the tools I needed to create my own custom SSL Reverse Proxy in the form of our eRPG SDK and GETURI software.  So, I contacted the credit card processing company and had them review my SSL website to see if it met their standards, which it did.  

The first step was to have the credit card processing company update the callback programs that were being used by changing the host name from my client's to https://www.bvstools.com.  

Next I created the program necessary to accept the request from the credit card processing company, pass that request on to my client (using GETURI), and then report the results from my client back to the credit card processing company.  With my web site acting as a proxy, the credit card processing company was only concerned about the security of my site, not my client's.

It ended up working very well and because of the great support from the credit card processing company we were able to get this up and going in less than an hour.

The resulting code is as follows:
 

 H DFTACTGRP(*NO) BNDDIR('ERPGSDK')                                    
  ****************************************************************     
  * Prototypes                                                   *     
  ****************************************************************     
  /COPY QCOPYSRC,P.ERPGSDK                                             
  /COPY QCOPYSRC,P.HTTPSTD                                             
  /COPY QCOPYSRC,P.LIBL                                                
  /COPY QCOPYSRC,GETURICOPY                                            
  ****************************************************************         
 D GetUriRG        pr                  extpgm('GETURIRG')                  
 D   G_In                              like(GetUri_In)                     
 D   G_Out                             like(GetUri_Out)                    
 D   G_Head                            like(GetUri_Head)                   
 D   G_Data                            like(GetUri_Data)                   
 D   G_MsgCd                           like(GetUri_MsgCd)                  
 D   G_Msg                             like(GetUri_Msg)                    
  ****************************************************************         
  * Data read in from page                                                 
 D postData        S          65535                                        
  ****************************************************************         
  /free                                                                    
                                                                           
   postData = #RdStin();                                                   
   #pushLib('GETURI');                                                     
                                                                           
   Clear GetUri_In;                                                        
   GI_URI = 'online.myclient.com/cgi-bin/ccpgm';                  
   GI_ReqMeth = 'POST';   
   GI_Data = postData;                                     
   GI_Port = 443;                                          
   GI_SSL = '*YES';                                        
   GI_OutType = '*RETURN';                                 
   GI_SprHead = '*YES';                                    
                                                           
   GetUriRG(GetUri_In:GetUri_Out:GetUri_Head:GetUri_Data:  
            GetUri_MsgCd:GetUri_Msg);   
                                                       
   #popLib('GETURI');                                  
                                                       
   #startUp();                                         
   #setImmediate(*ON);                                 
   #writeTemplate('stdhtmlheader.erpg');               
   #WrStout(Geturi_Out);                               
   #cleanUp();
                                
   *INLR = *ON;                                                                             
                                                                                                            

The steps involved are as follows:

  1. Read the data Standard Input "POST"ed to the website using the QtmhRdStin API (in this case it's the #RdStin subprocedure which is a wrapper for the API).
  2. Take the Standard Input data and use GETURI to make a POST to my client's webserver.  Using the Standard Input read from the original request means that this is basically mirroring the request to my client's server.
  3. When GETURI completes it will have the results that would have been generated by my client's server if they would have originally been used on the call in the variable GetUri_Out.  This data is then mirrored back to the credit card processing company.

All in all it was a pretty simple band-aid.  My client has already made a request to be updated to V7R3 and that is underway.  Once that is done, all that will be required is a new SSL certificate for their website that meets the credit card companies criteria and we can have them change their callback information back to my client's servers.

UPDATE:

I ran into an issue with ASCII to EBCDIC conversions for this.  When a system would send the @ sign escaped as %40, because my Apache server is set up with CGIConvMode as %%EBCDIC/EBCDIC%% it would convert that %40 to %7C, the EBCDIC representation of @ which in ASCII is | (a bar).

To remedy this I added a LocationMatch container for the proxy programs to set the CGIConvMode to %%MIXED/MIXED%% so that it would convert data from EBCDIC to ASCII but leave any of the escaped data as it is.

<LocationMatch /cgi-bin/(proxypgm1|proxypgm2)>
   CGIConvMode %%MIXED/MIXED%%
</LocationMatch>

This seems to have solved the issue.  I wonder if the IBM i will ever have the option to become an ASCII machine.  Boy, wouldn't that be nice!


Last edited 03/29/2018 at 15:11:09




Reply




© Copyright 1983-2024 BVSTools
GreenBoard(v3) Powered by the eRPG SDK, MAILTOOL Plus!, GreenTools for Google Apps, jQuery, jQuery UI, BlockUI, CKEditor and running on the IBM i (AKA AS/400, iSeries, System i).