sijms / go-ora

Pure go oracle client
MIT License
786 stars 174 forks source link

Large output buffers + NNE results in io.EOF disconnections #444

Closed bobvawter closed 11 months ago

bobvawter commented 11 months ago

I've found a case where go-ora 2.7.18 has its network connection terminated by Oracle 21c and 19c when there are large payloads being sent from the client to the server and Native Network Encryption is being used. I'm backfilling some data and using the bulk-transfer method. Above a certain batch size, I see an io.EOF error being returned.

I've been able to trace the behavior to how large buffers are being split:

https://github.com/sijms/go-ora/blob/09e66f57e7c518239a126347a6e45ea40aede73a/v2/network/session.go#L541-L546

When I change that magic constant on line 541 from -20 to -32, the error goes away.

I'm able to recreate the problem using the Oracle Express 21c docker image and by adding the following to sqlnet.ora:

SQLNET.ENCRYPTION_SERVER = REQUIRED
SQLNET.ENCRYPTION_TYPES_SERVER = AES256
SQLNET.ENCRYPTION_CLIENT = REQUIRED
SQLNET.ENCRYPTION_TYPES_CLIENT = AES256
SQLNET.CRYPTO_CHECKSUM_SERVER = REQUIRED
SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = SHA256
SQLNET.CRYPTO_CHECKSUM_TYPES_CLIENT = SHA256
SQLNET.CRYPTO_CHECKSUM_CLIENT  = REQUIRED
SQLNET.EXPIRE_TIME = 10

TLS is not in use.

I'm at a loss to explain why exactly this tweak makes a difference, when I measure the resulting buffer sizes after splitting.

# Added on line 552:
fmt.Printf("TDU:%d SDU:%d segmentLen:%d vs pck.length: %d len(pck.bytes()):%d\n", session.Context.TransportDataUnit, session.Context.SessionDataUnit, segmentLen, pck.length,len(pck.bytes()))

OK: -33
TDU:2097152 SDU:8192 segmentLen:8159 vs pck.length: 8204 len(pck.bytes()):8204

OK: -32
TDU:2097152 SDU:8192 segmentLen:8160 vs pck.length: 8204 len(pck.bytes()):8204

BAD: -31
TDU:2097152 SDU:8192 segmentLen:8161 vs pck.length: 8220 len(pck.bytes()):8220

BAD: -20
TDU:2097152 SDU:8192 segmentLen:8172 vs pck.length: 8220 len(pck.bytes()):8220

There's a 16-byte difference in the final packet size, but they're still larger than the SessionDataUnit value. You'd know far better than I if the SDU value is mandatory or a suggestion.