Table of contents
Preamble
Encrypting network traffic and controlling what access to what is not already a standard implemented everywhere but it starts to be more and more a classical request from security teams and audit companies. Starting with Oracle 10gR2 the Oracle Advanced Security enterprise edition option is no longer required to encrypt and authenticate network:
Network encryption (native network encryption and SSL/TLS) and strong authentication services (Kerberos, PKI, and RADIUS) are no longer part of Oracle Advanced Security and are available in all licensed editions of all supported releases of the Oracle database.
In below my database server is server1.domain.com (192.168.56.101) running Oracle database enterprise edition 12cR1 (12.1.0.2). Server2.domain.com (192.168.56.102) will be my Oracle client (12cR1, 12.1.0.2) and server3.domain.com (192.168.56.103) will be the node I will use to monitor network traffic. All virtual machines are running with Oracle Linux Server release 7.3 64 bits.
You can access to part 1 where we have introduced on how to isolate your database servers from unwanted connections…
Network encryption
The first thing I have asked myself is how to see that information are going in clear between my client and my server ? I have started to use world famous wireshark for the pretty graphical interface (even if product has been tough to configure) but you can also use well known tcpdump for simpler usage and its command line usage nice to copy/paste in a blog. Tcpdump is available in standard Oracle linux repository, so installation is as simple as:
[root@server3 ~]# yum install tcpdump |
To be able to monitor traffic between my database server and my client I have been obliged to change promiscuous mode of the Host-only Adapter lan card:
I create in my database below test table containing confidential sales figures:
SQL> DROP TABLE sales; TABLE dropped. SQL> CREATE TABLE sales 2 (region VARCHAR2(20), 3 val NUMBER) 4 TABLESPACE users; TABLE created. SQL> INSERT INTO sales VALUES('Europe',15587496); 1 ROW created. SQL> INSERT INTO sales VALUES('Asia/Pacific',25587425); 1 ROW created. SQL> INSERT INTO sales VALUES('US',12584789); 1 ROW created. SQL> COMMIT; COMMIT complete. SQL> SELECT * FROM sales; REGION VAL -------------------- ---------- Europe 15587496 Asia/Pacific 25587425 US 12584789 |
If you use tcpdump to monitor traffic you will see something like (I have also edited /etc/services to comment out 1531 port). I monitor traffic between my server (server1.domain.com) and my client (server2.domain.com) using a third node called server3.domain.com:
[root@server3 ~]# tcpdump -A host server2.domain.com and server1.domain.com and port 1531 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp0s3, link-type EN10MB (Ethernet), capture size 65535 bytes 17:35:41.181023 IP server2.32988 > server1.1531: Flags [P.], seq 2387244669:2387244970, ack 3577557774, win 460, options [nop,nop,TS val 27739139 ecr 27735720], length 301 E..ac.@.@.....8f..8e.....Jv}.=3.....@...... ................................................................................................W.......................................................................................select * from sales.................................................... 17:35:41.181749 IP server1.1531 > server2.32988: Flags [P.], seq 1:460, ack 301, win 427, options [nop,nop,TS val 27752932 ecr 27739139], length 459 E...*L@.@.....8e..8f.....=3..Jw.....Y...... ..y...D.....................n?.S.K....uxu....%*.......Q.............................i..................REGION..............................................................VAL...................xu...$).......................B............=...................................,...Europe...;Ka....aB..................................................... ...............................6................3...................................................................... 17:35:41.182025 IP server2.32988 > server1.1531: Flags [.], ack 460, win 483, options [nop,nop,TS val 27739140 ecr 27752932], length 0 E..4c.@.@.....8f..8e.....Jw..=4.....*...... ..D...y. 17:35:41.182346 IP server2.32988 > server1.1531: Flags [P.], seq 301:322, ack 460, win 483, options [nop,nop,TS val 27739141 ecr 27752932], length 21 E..Ic.@.@.....8f..8e.....Jw..=4......\..... ..D...y...................... 17:35:41.182798 IP server1.1531 > server2.32988: Flags [P.], seq 460:728, ack 322, win 427, options [nop,nop,TS val 27752933 ecr 27739141], length 268 E..@*M@.@..O..8e..8f.....=4..Jw......M..... ;0Z............{........... ...............................6................3..........................................................{............ORA-01403: no data found 17:35:41.222776 IP server2.32988 > server1.1531: Flags [.], ack 728, win 505, options [nop,nop,TS val 27739181 ecr 27752933], length 0 E..4c.@.@.....8f..8e.....Jw..=5.....)C..... ..D-..y. |
You might also install world famous Wireshark tool to see this graphically. On my Linux virtual machine installation is as simple as:
[root@server3 ~]# yum install wireshark.x86_64 [root@server3 ~]# yum install wireshark-gnome.x86_64 |
If you hit the display issue install required fonts (wondering why they are not by default):
[root@server3 ~]# yum install dejavu-sans-fonts.noarch dejavu-serif-fonts.noarch |
Using the same capture filter as with tcpdump:
As you can see the decoding for a dummy hacker like myself is not so obvious and, so far, I have not deeply investigated how to decode the number from ASCII characters. Instead of wasting too much time on this and keep my focus on encrypting feature I have changed the query to:
SQL> SELECT region, TO_CHAR(val) AS val FROM sales; REGION VAL -------------------- ---------------------------------------- Europe 15587496 Asia/Pacific 25587425 US 12584789 |
Doing the same tcpdump I now get:
[root@server3 ~]# tcpdump -A host server2.domain.com AND server1.domain.com AND port 1531 tcpdump: verbose output suppressed, USE -v OR -vv FOR full protocol DECODE listening ON enp0s3, link-TYPE EN10MB (Ethernet), capture SIZE 65535 bytes 17:36:08.466986 IP server2.32988 > server1.1531: Flags [P.], seq 2387244991:2387245341, ack 3577558501, win 505, options [nop,nop,TS val 27766425 ecr 27752933], LENGTH 350 E...c.@.@..e..8f..8e.....Jw..=5......T..... ................................................................................................W......................................................................................-SELECT region, TO_CHAR(val) AS val FROM sales.................................................... 17:36:08.467847 IP server1.1531 > server2.32988: Flags [P.], seq 1:459, ack 350, win 447, options [nop,nop,TS val 27780218 ecr 27766425], LENGTH 458 E...*N@.@.....8e..8f.....=5..Jy............ .'<.......Q.............................i..................REGION...................(.......................i...(..............VAL...................xu...% ......................"*............=............................X......Europe.15587496....aB.....................................................................................6................3...................................................................... 17:36:08.467960 IP server2.32988 > server1.1531: Flags [.], ack 459, win 528, options [nop,nop,TS val 27766426 ecr 27780218], length 0 E..4c.@.@.....8f..8e.....Jy..=7.....Q...... .......z 17:36:08.468222 IP server2.32988 > server1.1531: Flags [P.], seq 350:371, ack 459, win 528, options [nop,nop,TS val 27766426 ecr 27780218], length 21 E..Ic.@.@.....8f..8e.....Jy..=7............ .......z..................... 17:36:08.468622 IP server1.1531 > server2.32988: Flags [P.], seq 459:729, ack 371, win 447, options [nop,nop,TS val 27780219 ecr 27766426], length 270 E..B*O@.@..K..8e..8f.....=7..Jy2........... ...{..................................................................Asia/Pacific.25587425......US.12584789............{........... ...............................6................3..........................................................{............ORA-01403: no data found 17:36:08.508216 IP server2.32988 > server1.1531: Flags [.], ack 729, win 550, options [nop,nop,TS val 27766467 ecr 27780219], length 0 E..4c.@.@.....8f..8e.....Jy2.=8....&O...... .......{ |
Now the display is a bit more clearer, so much clearer that you can read them black on white in TCP/IP frames. No need to say that someone sniffing your network can grab highly confidential information…
You can define the desired encryption at client and server level with below parameters (default value is ACCEPTED):
- SQLNET.ENCRYPTION_CLIENT = accepted | rejected | requested | required
- SQLNET.ENCRYPTION_SERVER = accepted | rejected | requested | required
You define the encryption algorithm using below parameters at client and server level (by default all algorithms are selected):
- SQLNET.ENCRYPTION_TYPES_SERVER = (3des112, 3des168, aes128, aes192, aes256, des, des40, rc4_40, rc4_56, rc4_128, rc4_256)
- SQLNET.ENCRYPTION_TYPES_CLIENT = (3des112, 3des168, aes128, aes192, aes256, des, des40, rc4_40, rc4_56, rc4_128, rc4_256)
CLient and server must have a common encryption algorithm to be able to initiate the connection or below error message is thrown:
ERROR:
ORA-12650: No common encryption or data integrity algorithm |
Means that in the case of multiple clients connecting to a single server, you can configure only the server and all clients will benefit by default from encryption. Below table extracted from official Oracle documentation explain how negotiation is performed:
Client Setting | Server Setting | Encryption and Data Negotiation |
---|---|---|
REJECTED | REJECTED | OFF |
ACCEPTED | REJECTED | OFF |
REQUESTED | REJECTED | OFF |
REQUIRED | REJECTED | Connection fails |
REJECTED | ACCEPTED | OFF |
ACCEPTED | ACCEPTED | OFF (This value defaults to OFF. Cryptography and data integrity are not enabled until the user changes this parameter by using Oracle Net Manager or by modifying the sqlnet.ora file.)> |
REQUESTED | ACCEPTED | ON |
REQUIRED | ACCEPTED | ON |
REJECTED | REQUESTED | OFF |
ACCEPTED | REQUESTED | ON |
REQUESTED | REQUESTED | ON |
REQUIRED | REQUESTED | ON |
REJECTED | REQUIRED | Connection fails |
ACCEPTED | REQUIRED | ON |
REQUESTED | REQUIRED | ON |
REQUIRED | REQUIRED | ON |
So in sqlnet.ora file of your database server you only have to set. I have chosen REQUIRED value but REQUESTED would do the job. Here it means that clients that have specifically set REJECTED will not be able to connect:
SQLNET.ENCRYPTION_SERVER = required SQLNET.ENCRYPTION_TYPES_SERVER= (AES256) |
You can also use netmgr but the tool will force you to set deprecated SQLNET.CRYPTO_SEED parameter:
SQLNET.CRYPTO_SEED
This parameter was used to seed a random number generator for Oracle Advanced Security. Starting with Oracle Database 10g, Oracle Advanced Security uses a random number generator that does not to require a user-supplied seed value. Last Supported Release 9.2 (9iR2).
If you set SQLNET.ENCRYPTION_CLIENT = REJECTED in client sqlnet.ora then your client will not be able to connect throwing below error message:
ERROR:
ORA-12660: Encryption or crypto-checksumming parameters incompatible |
If you sniff again the network between your client and you newly configured encrypted database server you can see that traffic is much less readable:
[root@server3 ~]# tcpdump -A host server2.domain.com and server1.domain.com and port 1531 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp0s3, link-type EN10MB (Ethernet), capture size 65535 bytes 18:01:19.041724 IP server2.32991 > server1.1531: Flags [P.], seq 1900443499:1900443831, ack 372174552, win 488, options [nop,nop,TS val 29277000 ecr 29283750], length 332 E.....@.@.G...8f..8e....qFwk........r1..... ...H.......L. ..........:.D......S..)`0/~..cc...........;.>.x,...,..6.!.&.u.d...X...b....n.()y..F.k..%o..Yc......<Z...Zj......W....Ve..tT.<eB#b7u.A`6..T.Z)...)...p]yX1.{..p.|.O..(........d..Ezb...sX.W.?..%W...r......5lr..zg.$........9.9...M3./'......D...V......ceHg...?+.kZ._......n..i;._.(.5.1.....>....0.H ReA~...^.+......p.W E....Z...N.. 18:01:19.042807 IP server1.1531 > server2.32991: Flags [P.], seq 1:461, ack 332, win 436, options [nop,nop,TS val 29290793 ecr 29277000], length 460 E....l@.@.?p..8e..8f........qFx.....h...... 8.K..2.Q..+..|..v3...g.!{G]...i....4.cx....f..$..09k.=.........cWagr.S..'.....'y.@.;.....J..{..[.~.1.D....<.],...N.....C...qC.O.......I,.!...Y.ds..]...>.....Z.{HE..+.5hy.Mr.>........L...?k.W..-9.O.N.A....9S.L.C..c...]..Tn... ....6..K...CA......%. .:F&..8&...f:o"Uc9.s...Z.... .Kc...]. .p.N...VLh..3V.wDaP\....G}3..V.c...>....)..n..O./.E...He]..pM5J.........$..S...J...@C....2.\.W...A/+..Z.z]+.... 18:01:19.043039 IP server2.32991 > server1.1531: Flags [.], ack 461, win 510, options [nop,nop,TS val 29277001 ecr 29290793], length 0 E..4..@.@.I...8f..8e....qFx.........[...... ...I...) 18:01:19.043361 IP server2.32991 > server1.1531: Flags [P.], seq 332:360, ack 461, win 510, options [nop,nop,TS val 29277002 ecr 29290793], length 28 E..P..@.@.H...8f..8e....qFx................ ...J...)..... ....h...-..4t.[..b#... 18:01:19.043849 IP server1.1531 > server2.32991: Flags [P.], seq 461:745, ack 360, win 436, options [nop,nop,TS val 29290794 ecr 29277002], length 284 E..P.m@.@.@...8e..8f........qFx.....$...... ...*...J..... .....d..0NM.2......3...$..e)ss"..,"B_t.9.I:.&..,.....v.m.Q............V.g.j..K0....@.^.&&L....:,Lz.,.......F..NF..vp.7....?=$D...@. .m......Z.su9K.v......".........p..........y]^O.[}E.../...\v..X...-...V/.........q.(......'....c..9<...8.X-....f=/......H............('.P....4.. 18:01:19.083335 IP server2.32991 > server1.1531: Flags [.], ack 745, win 533, options [nop,nop,TS val 29277042 ecr 29290794], length 0 E..4..@.@.I...8f..8e....qFx.........Y...... ...r...* |
I have also been asked on the important performance penalty of such security measure. In Oracle official documentation the only reference to performance is a quote about the biger impact of 3DES algorithm:
3DES provides a high degree of message security, but with a performance penalty. The magnitude of the performance penalty depends on the speed of the processor performing the encryption. 3DES typically takes three times as long to encrypt a data block when compared to the standard DES algorithm.
Except this Oracle quote not much about it on except one article from OraFAQ done with Oracle 10gR2. MD5 and SHA-1 columns is a club with Network Integrity parameters that we see in next chapter:
Algorithm | None | MD5 | SHA-1 | |||
---|---|---|---|---|---|---|
Time | %None | Time | %None | Time | %None | |
None | 79.6 s | 80.5 s | 101% | 82.4 s | 104% | |
DES | 104.7 s | 132% | 107.1 s | 135% | 108.2 s | 136% |
3DES168 | 151.8 s | 191% | 153.9 s | 193% | 155.6 s | 196% |
AES128 | 88.8 s | 112% | 90.5 s | 114% | 92.1 s | 116% |
AES256 | 91.8 s | 115% | 93.5 s | 117% | 94.2 s | 118% |
RC4_128 | 81.6 s | 103% | 82.5 s | 104% | 85.0 s | 107% |
RC4_256 | 81.7 s | 103% | 82.8 s | 104% | 85.0 s | 107% |
I would say that nowadays security being a main concern I would personally not bother that much with performance impact of this network encryption… But still if you client and database server exchange a lot of information plan performance test before rushing to production… We can, at least, see that 3DES168 is almost doubling response time…
Network integrity
Network integrity aims at ensuring that data has not been modified between the client and the server (data modification attack). It also aims at ensuring the same transaction will not be send multiple time to compromise your system (data replay attack). Testing it is not as easy as with network encryption unfortunately…
To activate it you set below parameters at client or server level, the possible value at client and server work the same as with network encryption (default value is ACCEPTED):
- SQLNET.CRYPTO_CHECKSUM_SERVER = accepted | rejected | requested | required
- SQLNET.CRYPTO_CHECKSUM_CLIENT = accepted | rejected | requested | required
You then choose checksum algorithm, client and server must have one in common to work (by default all algorithms are chosen):
- SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = (MD5, SHA1, SHA256, SHA384, SHA512)
- SQLNET.CRYPTO_CHECKSUM_TYPES_CLIENT = (MD5, SHA1, SHA256, SHA384, SHA512)
I have chosen to activate it, same as before, only at database server level. By default all is ready on client to proceed:
SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = (SHA1) SQLNET.CRYPTO_CHECKSUM_SERVER = required |
This can also be done with netmgr:
Here below the tcpdump result with encryption, we simply see that all TCP/IP frames are a bit longer than the initial output making me think that checksum (network integrity) has been added:
[root@server3 ~]# tcpdump -A host server2.domain.com and server1.domain.com and port 1531 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp0s3, link-type EN10MB (Ethernet), capture size 65535 bytes 10:36:50.366041 IP server2.32995 > server1.1531: Flags [P.], seq 2461874204:2461874552, ack 3658538857, win 488, options [nop,nop,TS val 89008324 ecr 89012257], length 348 E...".@.@.$r..8f..8e......8....i........... .................................................................................................L.....................................................................................-select region, to_char(val) as val from sales....................................................."...yW.T...e....{... 10:36:50.367147 IP server1.1531 > server2.32995: Flags [P.], seq 1:480, ack 348, win 438, options [nop,nop,TS val 89022117 ecr 89008324], length 479 E....<@.@.T...8e..8f.......i..9x....a^..... ........."*.........................................X......Europe.15587496.....C.....................................................................................6.........................................................................................F.#..]...yA.F..x@c. 10:36:50.367404 IP server2.32995 > server1.1531: Flags [.], ack 480, win 510, options [nop,nop,TS val 89008326 ecr 89022117], length 0 E..4".@.@.%...8f..8e......9x...H.....-..... .N(..N^. 10:36:50.367733 IP server2.32995 > server1.1531: Flags [P.], seq 348:390, ack 480, win 510, options [nop,nop,TS val 89008326 ecr 89022117], length 42 E..^".@.@.%...8f..8e......9x...H........... .N(..N^....*. ....................&..=.!t.)M.%.my. 10:36:50.368078 IP server1.1531 > server2.32995: Flags [P.], seq 480:771, ack 390, win 438, options [nop,nop,TS val 89022118 ecr 89008326], length 291 E..W.=@.@.UG..8e..8f.......H..9......;..... .N^..N(....#. ........................................................Asia/Pacific.25587425......US.12584789............{........... ...............................6...........................................................................{............ORA-01403: no data found J......'l...O..x!".+. 10:36:50.408468 IP server2.32995 > server1.1531: Flags [.], ack 771, win 533, options [nop,nop,TS val 89008367 ecr 89022118], length 0 E..4".@.@.%...8f..8e......9....k........... .N(..N^. |
Network strong authentication
By default database users are authenticated with their passwords (whether it is through network or with Operating System for OS authenticated users). If you want to move a step forward in security you might wish to implement what is called strong authentication using third party authentication services (Kerberos and Radius) or SSL with digital certificates.
As just written there are multiple methods to implement strong authentication:
- Kerberos
- Remote Authentication Dial-In User Service (RADIUS)
- Secure Sockets Layer
The authentication method I plan to test is Secure Sockets Layer. It works with certificates stored in Oracle wallet to authenticate clients and server. I will obviously not worked with certificate signed by an authorized authority (Comodo, Verizon,…) but with self signed certificates that must not obviously be used in production.
My Oracle Support (MOS) has plenty of documentation on how to do it, I tend to say maybe too much as I had to mix multiple notes to reach a working environment.
With orapki
I wanted to use graphical Oracle Wallet Manager (OWM) to do it but after many unsuccessful tries I have realized that this tool cannot be used in the case of self signed certificates. Or maybe my knowledge is too poor…
The first time you execute OWM:
You will get a popup asking to create the default directory, I have chosen to do it and use this directory to store the wallet I will finally create with command line tools. This way it is more convenient to graphically control all is going well:
The tool to use is orapki. Start by creating a wallet. The wallet is created with auto_login option to avoid being obliged to supply password to use it (password will be asked only in case of modifications):
[oracle@server1 ~]$ cd /u01/app/oracle/product/12.1.0/dbhome_1/owm/wallets/oracle [oracle@server1 oracle]$ ll total 0 [oracle@server1 oracle]$ orapki wallet create -wallet . -auto_login -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 8 -rw------- 1 oracle dba 120 Feb 9 12:04 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Feb 9 12:04 cwallet.sso.lck -rw------- 1 oracle dba 75 Feb 9 12:04 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Feb 9 12:04 ewallet.p12.lck |
Add a self-signed certificate to your wallet:
[oracle@server1 oracle]$ orapki wallet add -wallet . -dn 'CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH' -keysize 2048 -self_signed -validity 365 -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 8 -rw------- 1 oracle dba 4085 Feb 9 12:06 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Feb 9 12:04 cwallet.sso.lck -rw------- 1 oracle dba 4040 Feb 9 12:06 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Feb 9 12:04 ewallet.p12.lck [oracle@server1 oracle]$ orapki wallet display -wallet . Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Requested Certificates: User Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH Trusted Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH |
Export the server certificate to import it in your clients’ wallet:
[oracle@server1 oracle]$ orapki wallet export -wallet . -dn 'CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH' -cert server_ca.cert Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 12 -rw------- 1 oracle dba 4085 Feb 9 12:06 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Feb 9 12:04 cwallet.sso.lck -rw------- 1 oracle dba 4040 Feb 9 12:06 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Feb 9 12:04 ewallet.p12.lck -rw------- 1 oracle dba 1123 Feb 9 15:13 server_ca.cert |
If you control graphically what has been done you get:
Do almost the same thing on your client. Start by creating an auto login wallet:
[oracle@server2 ~]$ cd /u01/app/oracle/product/12.1.0/dbhome_1/owm/wallets/oracle [oracle@server2 oracle]$ ll total 0 [oracle@server2 oracle]$ orapki wallet create -wallet . -auto_login -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server2 oracle]$ ll total 8 -rw------- 1 oracle dba 120 Feb 9 15:20 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Feb 9 15:20 cwallet.sso.lck -rw------- 1 oracle dba 75 Feb 9 15:20 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Feb 9 15:20 ewallet.p12.lck |
Add a self signed certificate to your wallet (here I create a certificate for an user I plan to call yjaquier):
[oracle@server2 oracle]$ orapki wallet add -wallet . -dn 'CN=yjaquier,O=MyCompany,L=Geneva,C=CH' -keysize 2048 -self_signed -validity 365 -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. |
Export your client certificate for server wallet import:
[oracle@server2 oracle]$ orapki wallet export -wallet . -dn 'CN=yjaquier,O=MyCompany,L=Geneva,C=CH' -cert client_ca.cert Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server2 oracle]$ ll total 12 -rw------- 1 oracle dba 1095 Feb 9 15:21 client_ca.cert -rw------- 1 oracle dba 4037 Feb 9 15:20 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Feb 9 15:20 cwallet.sso.lck -rw------- 1 oracle dba 3992 Feb 9 15:20 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Feb 9 15:20 ewallet.p12.lck |
Then transfer on client with ssh server certificated and vice-versa. Then on client import server certificate as a trusted one:
[oracle@server2 oracle]$ orapki wallet add -wallet . -trusted_cert -cert server_ca.cert -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. |
Import on server client certificate as a trusted one:
[oracle@server1 oracle]$ orapki wallet add -wallet . -trusted_cert -cert client_ca.cert -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. |
At the end you should get on server:
Now comes the Oracle network configuration. In listener.ora file I have added the listening on secure TCP port (tcps) and wallet location:
LISTENER_ORCL = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = server1.domain.com)(PORT = 1531)) (ADDRESS = (PROTOCOL = TCPS)(HOST = server1.domain.com)(PORT = 1532)) ) ) WALLET_LOCATION = (SOURCE= (METHOD=file) (METHOD_DATA= (DIRECTORY=/u01/app/oracle/product/12.1.0/dbhome_1/owm/wallets/oracle) ) ) |
in sqlnet.ora of server I also add wallet location:
WALLET_LOCATION = (SOURCE= (METHOD=file) (METHOD_DATA= (DIRECTORY=/u01/app/oracle/product/12.1.0/dbhome_1/owm/wallets/oracle) ) ) |
I had to stop and restart the listener to make it working and you can control it is activated with:
[oracle@server1 admin]$ lsnrctl status listener_orcl LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 09-MAR-2017 15:08:48 Copyright (c) 1991, 2014, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server1.domain.com)(PORT=1531))) STATUS of the LISTENER ------------------------ Alias listener_orcl Version TNSLSNR for Linux: Version 12.1.0.2.0 - Production Start Date 09-MAR-2017 12:52:53 Uptime 0 days 2 hr. 15 min. 55 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/oracle/product/12.1.0/dbhome_1/network/admin/listener.ora Listener Log File /u01/app/oracle/diag/tnslsnr/server1/listener_orcl/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=server1)(PORT=1531))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=server1)(PORT=1532))) Services Summary... Service "orcl" has 1 instance(s). Instance "orcl", status READY, has 1 handler(s) for this service... Service "pdb1" has 1 instance(s). Instance "orcl", status READY, has 1 handler(s) for this service... The command completed successfully |
Few parameters must be set at instance level:
SQL> show parameter authent NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ os_authent_prefix string ops$ remote_os_authent BOOLEAN FALSE SQL> ALTER SYSTEM SET os_authent_prefix='' scope=spfile; SYSTEM altered. SQL> show parameter authent NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ os_authent_prefix string ops$ remote_os_authent BOOLEAN FALSE SQL> shutdown IMMEDIATE DATABASE closed. DATABASE dismounted. ORACLE instance shut down. SQL> startup ORACLE instance started. Total SYSTEM Global Area 1073741824 bytes Fixed SIZE 2932632 bytes Variable SIZE 796917864 bytes DATABASE Buffers 268435456 bytes Redo Buffers 5455872 bytes DATABASE mounted. DATABASE opened. SQL> show parameter authent NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ os_authent_prefix string remote_os_authent BOOLEAN FALSE SQL> ALTER pluggable DATABASE pdb1 OPEN; Pluggable DATABASE altered. |
I also create the test user (yaquier, same as in client certificate) for network strong authentication:
SQL> alter session set container=pdb1; Session altered. SQL> create user yjaquier identified externally as 'CN=yjaquier,O=MyCompany,L=Geneva,C=CH'; User created. SQL> grant dba to yjaquier; Grant succeeded. |
In sqlnet.ora of client I also add wallet location:
WALLET_LOCATION = (SOURCE= (METHOD=file) (METHOD_DATA= (DIRECTORY=/u01/app/oracle/product/12.1.0/dbhome_1/owm/wallets/oracle) ) ) |
If you control with netmgr you get this on server:
And on client:
Remark
The documentation on MOS is asking you to set plenty of other parameters but for most of them the default value is more than sufficient. In fact I have been able to make the feature working without setting them.
Then you can test your listener is answering on both secure and unsecure ports:
[oracle@server2 ~]$ tnsping "(ADDRESS=(PROTOCOL=tcp)(HOST=server1.domain.com)(PORT=1531))" TNS Ping Utility for Linux: Version 12.1.0.2.0 - Production on 09-MAR-2017 15:32:25 Copyright (c) 1997, 2014, Oracle. All rights reserved. Attempting to contact (ADDRESS=(PROTOCOL=tcp)(HOST=server1.domain.com)(PORT=1531)) OK (0 msec) [oracle@server2 ~]$ tnsping "(ADDRESS=(PROTOCOL=tcps)(HOST=server1.domain.com)(PORT=1532))" TNS Ping Utility for Linux: Version 12.1.0.2.0 - Production on 09-MAR-2017 15:32:30 Copyright (c) 1997, 2014, Oracle. All rights reserved. Attempting to contact (ADDRESS=(PROTOCOL=tcps)(HOST=server1.domain.com)(PORT=1532)) OK (30 msec) |
To ease connection I create in tnsnames.ora of my clients the below entries (with my configuration it is still possible to connect on classic TCP port while at the end you should remove it):
PDB1 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = server1.domain.com)(PORT = 1531)) ) (CONNECT_DATA = (SERVICE_NAME = pdb1) ) ) PDB1S = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCPS)(HOST = server1.domain.com)(PORT = 1532)) ) (CONNECT_DATA = (SERVICE_NAME = pdb1) ) ) |
[oracle@server2 admin]$ sqlplus /@pdb1s SQL*Plus: Release 12.1.0.2.0 Production on Thu Mar 9 15:30:21 2017 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics, Real Application Testing and Unified Auditing options SQL> show user USER is "YJAQUIER" SQL> select sys_context('userenv','network_protocol') from dual; SYS_CONTEXT('USERENV','NETWORK_PROTOCOL') -------------------------------------------------------------------------------- tcps |
It is anyway still possible to connect in standard way supplying the password (not on command line obviously !!):
[oracle@server2 ~]$ sqlplus test/secure_password@pdb1s SQL*Plus: Release 12.1.0.2.0 Production on Thu Mar 9 15:42:45 2017 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics, Real Application Testing and Unified Auditing options SQL> select sys_context('userenv','network_protocol') from dual; SYS_CONTEXT('USERENV','NETWORK_PROTOCOL') -------------------------------------------------------------------------------- tcps |
If you test this from a third client where certificate has not been inserted in server wallet you should be unable to connect:
[oracle@server3 ~]$ tnsping "(ADDRESS=(PROTOCOL=tcp)(HOST=server1.domain.com)(PORT=1531))" TNS Ping Utility for Linux: Version 12.1.0.2.0 - Production on 09-MAR-2017 15:32:44 Copyright (c) 1997, 2014, Oracle. All rights reserved. Attempting to contact (ADDRESS=(PROTOCOL=tcp)(HOST=server1.domain.com)(PORT=1531)) OK (50 msec) [oracle@server3 ~]$ tnsping "(ADDRESS=(PROTOCOL=tcps)(HOST=server1.domain.com)(PORT=1532))" TNS Ping Utility for Linux: Version 12.1.0.2.0 - Production on 09-MAR-2017 15:32:50 Copyright (c) 1997, 2014, Oracle. All rights reserved. Attempting to contact (ADDRESS=(PROTOCOL=tcps)(HOST=server1.domain.com)(PORT=1532)) TNS-12560: TNS:protocol adapter error [oracle@server3 ~]$ sqlplus test/secure_password@pdb1s SQL*Plus: Release 12.1.0.2.0 Production on Thu Mar 9 16:04:06 2017 Copyright (c) 1982, 2014, Oracle. All rights reserved. ERROR: ORA-28759: failure to open file Enter user-name: |
The above error is the one you will get if the wallet is not configured, if you configure it (without server certificate) you would get:
[oracle@server3 admin]$ sqlplus test/secure_password@pdb1s SQL*Plus: Release 12.1.0.2.0 Production on Thu Mar 9 16:57:51 2017 Copyright (c) 1982, 2014, Oracle. All rights reserved. ERROR: ORA-29024: Certificate validation failure Enter user-name: |
With openssl
Instead of using orapki I have tried to use openssl command to generate certificates and to signed them but it did not worked as expected…
First I have asked myself if I should use DSA or RSA and found the answer in Archlinux:
OpenSSH 7.0 deprecated and disabled support for DSA keys due to discovered vulnerabilities, therefore the choice of cryptosystem lies within RSA or one of the two types of ECC.
I have started be generating a root RSA 2048 bits key (I’m working in ~oracle/openssl directory):
[oracle@server1 openssl]$ openssl genrsa -out root.key 2048 Generating RSA private key, 2048 bit long modulus ...............+++ ......................................+++ e is 65537 (0x10001) [oracle@server1 openssl]$ ll total 4 -rw-r--r-- 1 oracle dba 1766 Feb 9 11:46 root.key |
Self-signed the root certificate with:
[oracle@server1 openssl]$ openssl req -x509 -new -nodes -key root.key -sha256 -days 1024 -out self-root.pem You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CH State or Province Name (full name) []: Locality Name (eg, city) [Default City]:Geneva Organization Name (eg, company) [Default Company Ltd]:MyCompany Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:server1.domain.com Email Address []: [oracle@server1 openssl]$ ll total 8 -rw-r--r-- 1 oracle dba 1675 Mar 8 15:33 root.key -rw-r--r-- 1 oracle dba 1253 Mar 8 15:38 self-root.pem |
The Distinguish Name (DN) of your self-signed root certificate is:
CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH
Create the wallet (I have chosen default OWM directory) with orapki (can be done with graphical interface):
[oracle@server1 oracle]$ cd $ORACLE_HOME/owm/wallets/oracle [oracle@server1 oracle]$ orapki wallet create -wallet . -pwd secure_password -auto_login Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 8 -rw------- 1 oracle dba 120 Mar 8 15:42 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Mar 8 15:42 cwallet.sso.lck -rw------- 1 oracle dba 75 Mar 8 15:42 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Mar 8 15:42 ewallet.p12.lck |
Add the self signed root certificate you have created before:
[oracle@server1 oracle]$ cd $ORACLE_HOME/owm/wallets/oracle [oracle@server1 oracle]$ orapki wallet add -wallet . -trusted_cert -cert ~oracle/openssl/self-root.pem -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 8 -rw------- 1 oracle dba 1189 Mar 8 15:44 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Mar 8 15:42 cwallet.sso.lck -rw------- 1 oracle dba 1144 Mar 8 15:44 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Mar 8 15:42 ewallet.p12.lck [oracle@server1 oracle]$ orapki wallet display -wallet . Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Requested Certificates: User Certificates: Trusted Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH |
Generate the certificate signing request (CSR):
[oracle@server1 oracle]$ orapki wallet add -wallet . -dn "CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH" -keysize 1024 -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ orapki wallet display -wallet . Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Requested Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH User Certificates: Trusted Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH |
Export the CSR using:
[oracle@server1 oracle]$ orapki wallet export -wallet . -dn "CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH" -request self-signed-oracle.csr -pwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 12 -rw------- 1 oracle dba 2429 Mar 8 15:46 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Mar 8 15:42 cwallet.sso.lck -rw------- 1 oracle dba 2384 Mar 8 15:46 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Mar 8 15:42 ewallet.p12.lck -rw------- 1 oracle dba 621 Mar 8 15:47 self-signed-oracle.csr |
Trying to sign the CSR with the server self-signed certificate did not worked:
[oracle@server1 openssl]$ ll total 12 -rw-r--r-- 1 oracle dba 1675 Mar 8 15:33 root.key -rw-r--r-- 1 oracle dba 1253 Mar 8 15:38 self-root.pem -rw------- 1 oracle dba 621 Mar 8 15:47 self-signed-oracle.csr [oracle@server1 openssl]$ openssl x509 -req -in self-signed-oracle.csr -CA self-root.pem -CAkey root.key -CAcreateserial -out self-signed-oracle.crt -days 365 -sha256 Signature verification error 140156873422752:error:0D0C50A1:asn1 encoding routines:ASN1_item_verify:unknown message digest algorithm:a_verify.c:191: |
My server is perfectly up to date (as of writing of this blog post) and I have unfortunately not found how to overcome this error… If someone has an idea feel free to comment…
With keytool
Keytool is coming with Java and I have seen it used by Tim Hall, this would be by far my last choice but I wanted to see if I get the same issues as with openssl. Create a Java KeyStore (JKS) containing a self-signed certificate:
[oracle@server1 ~]$ cd $ORACLE_HOME/owm/wallets/oracle [oracle@server1 oracle]$ keytool -genkeypair -keyalg RSA -keysize 2048 -alias selfsigned -keystore keystore.jks -dname 'CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH' -storepass secure_password -validity 365 -keypass secure_password [oracle@server1 oracle]$ ll total 4 -rw-r--r-- 1 oracle dba 2190 Feb 10 12:55 keystore.jks |
Create an empty wallet:
[oracle@server1 oracle]$ orapki wallet create -wallet . -pwd secure_password -auto_login Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ ll total 12 -rw------- 1 oracle dba 120 Feb 10 12:56 cwallet.sso -rw-rw-rw- 1 oracle dba 0 Feb 10 12:56 cwallet.sso.lck -rw------- 1 oracle dba 75 Feb 10 12:56 ewallet.p12 -rw-rw-rw- 1 oracle dba 0 Feb 10 12:56 ewallet.p12.lck -rw-r--r-- 1 oracle dba 2190 Feb 10 12:55 keystore.jks |
Import the Java KeyStore (JKS) into the wallet:
[oracle@server1 oracle]$ orapki wallet jks_to_pkcs12 -wallet . -pwd secure_password -keystore keystore.jks -jkspwd secure_password Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. [oracle@server1 oracle]$ orapki wallet display -wallet . Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Requested Certificates: User Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH Trusted Certificates: Subject: CN=server1.domain.com,O=MyCompany,L=Geneva,C=CH |
All worked fine and I got same result as with orapki, so not encountering any issue !
Securing database network conclusion
Before 12cR1 even if you have found an huge interest in network encryption, checksum and strong authentication the advanced security enterprise edition option price might have been a stopper in its implementation.
This is finally no more true and nothing should prevent you to, at least, implement network encryption and checksum as it require really low effort. You can still implement it from your database server in an optimistic way, means by not forbidding client connection that do not want to implement it…
References
- Overview and Configuration of Oracle Network Encryption (Doc ID 76629.1)
- How To Configure SSL Authentication And Encryption Using Self Signed Certificates In A Multitenant Environment (Doc ID 2099733.1)
- Configuring SSL for Client Authentication and Encryption With Self Signed Certificates On Both Ends Using orapki (Doc ID 401251.1)
- Step by Step Guide To Configure SSL Authentication (Doc ID 736510.1)
- A Simple Example of a TCPS Loopback Connection Using OpenSSL. (Doc ID 262394.1)
- Configuring SSL Authentication With Client Certificates Signed By The Server Using orapki (Doc ID 1381035.1)
- Using Orapki as Certificate Authority (Doc ID 1489301.1)
- HOW TO: Setting up Encrypted Communications Channels in Oracle Database
- Introduction to Strong Authentication
- Configuring Network Data Encryption and Integrity (http://docs.oracle.com/database/121/DBSEG/asoconfg.htm#DBSEG020)
- Using the orapki Utility to Manage PKI Elements
- SSH keys
- keytool
- Using SSL With AWS Database Migration Service
- Various Types of SSL Commands and Keytool
- Creating Self-Signed SSL Certificates
- OraFAQ Network Encryption