I'm trying to make stunnel wrapped ppp connection to achieve bidirectional data transfer over stunnel like shown below.
Stunnel client --connect--> Stunnel server pppd client --connect--> pppd server 10.0.1.2 <--data--> 10.0.1.1
OpenBSD 6.4amd64 with Stunnel 5.44 server works till stunnel retries 'exec = pppd' section once stunnel client is reconnected. Also 'exec = pppd' section retries after a short network related communication lag also. Previous 'pppd' child instance haven't killed by stunnel 5.44 before new instance started.
So second 'pppd' process started and runs simultaneously with the first 'pppd' and link down. Restarting Stunnel server can clear child 'pppd' processes. So newly reestablished 'pppd' link between 10.0.1.1 <--> 10.0.1.2 endpoints works till next interconnection.
Does stunnel server have an option to start only one instance in 'exec' section or what should be done to fix this?
Any suggestions highly appreciated.
# ps -axu | grep pppd user 43231 0.0 0.0 476 0:00.01 persist lock passive 10.0.1.1:10.0.1.2 local noauth (pppd) user 39187 0.0 0.0 468 0:00.01 persist lock passive 10.0.1.1:10.0.1.2 local noauth (pppd)
# tail -n 10 /var/log/daemon pppd[39187] pppd 2.3.5 started by user, uid 0 pppd[43231] Using interface ppp1 pppd[43231] Connect: ppp0 <--> /dev/ttyp2 pppd[43231] Local IP address 10.0.1.1 pppd[43231] Remote IP address 10.0.1.2 pppd[39187] pppd 2.3.5 started by user, uid 0 pppd[39187] Using interface ppp0 pppd[39187] Connect: ppp0 <--> /dev/ttyp5 pppd[39187] Couldn't set interface address: Address 10.0.1.1 or destination 10.0.1.2 already exists
Stunnel configurations for server and client:
1. Server's configuration ... foreground = yes debug = 7
socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 ;socket = l:SO_LINGER=1:60
; Session cache sessionCacheSize = 100 sessionCacheTimeout = 600
stack = 65536
TIMEOUTbusy = 600 TIMEOUTconnect = 10 TIMEOUTidle = 43200 TIMEOUTclose = 5
[ppp] accept = LOCAL-IP:PORT exec = /usr/sbin/pppd execargs = lock 10.0.1.1:10.0.1.2 local debug noauth ;execargs = lock passive 10.0.1.1:10.0.1.2 local debug noauth pty = yes CAfile = ca.crt cert = server.crt key = server.key verifyChain = yes
2. Stunnel client's configuration ... foreground = yes debug = 7
socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1
; Session cache sessionCacheSize = 1 sessionCacheTimeout = 600
failover = rr
[ppp] client = yes retry = yes connect = REMOTE-IP:PORT exec = /usr/sbin/pppd execargs = defaultroute persist lock passive 10.0.1.2:10.0.1.1 local debug noauth name ppp-client pty = yes CAfile = ca.crt cert = client.crt key = client.key verifyChain = yes checkHost = REMOTE-HOSTNAME ;checkIP = 1.2.3.4
On Mon, May 13, 2019 at 04:07:57PM +0000, Martin Got wrote:
I'm trying to make stunnel wrapped ppp connection to achieve bidirectional data transfer over stunnel like shown below.
Stunnel client --connect--> Stunnel server pppd client --connect--> pppd server 10.0.1.2 <--data--> 10.0.1.1
OpenBSD 6.4amd64 with Stunnel 5.44 server works till stunnel retries 'exec = pppd' section once stunnel client is reconnected. Also 'exec = pppd' section retries after a short network related communication lag also. Previous 'pppd' child instance haven't killed by stunnel 5.44 before new instance started.
So second 'pppd' process started and runs simultaneously with the first 'pppd' and link down. Restarting Stunnel server can clear child 'pppd' processes. So newly reestablished 'pppd' link between 10.0.1.1 <--> 10.0.1.2 endpoints works till next interconnection.
Does stunnel server have an option to start only one instance in 'exec' section or what should be done to fix this?
Unfortunately, stunnel was not designed for your use case; it was designed to allow many different clients to make use of different instances of the same server program, one instance per client.
You might try to do something else: if you really only have a single PPP client and you can really guarantee that anything that connects to stunnel must reuse the same connection, you could write a separate program that listens on a TCP port or on a local Unix socket, waits for the first connection, starts an instance of pppd, and then, from that point on, sends all the traffic from this instance to all the connections that it has received, even if a new connection appears before the old one has been torn down. Then you can point stunnel to the local Unix socket of that service, and anything that connects to stunnel will establish a new connection to your service, but it will not matter, since your service will be written in such a way as to send all the traffic to all the connections. So the service should do something like:
1. Create a local Unix socket and start listening on it.
2. Wait for the first connection.
3. Start an instance of pppd (at most one instance shall be running at any point in time)
4. Keep waiting for new connections; accept any and treat them all in the same way.
5. If any data comes from a remote connection, send it to pppd.
6. If any data comes from pppd, send it to *all* the remote connections.
7. If any of the remote connections is closed, well, so be it, good riddance, another one will come along presently (or maybe another one has already come along and has started talking to pppd through this service).
8. If the pppd child process dies, close all the remote connections and go back to step 2.
Then you shall only have a problem if there are two "real" connections from different places at the same time - but if I understand your setup correctly, this should not really happen, since it is only you (your laptop or something like that) that connects to the PPP server.
If you want, I could try to whip up some simple implementation of such a pseudo-multiplexer.
G'luck, Peter