1 #define _XOPEN_SOURCE 500
9 #include <netinet/in.h>
14 #include "libsmooth.h"
19 struct keyvalue
*kv
= NULL
;
20 FILE *ifacefile
= NULL
;
22 char redif
[STRING_SIZE
];
23 char blueif
[STRING_SIZE
];
24 char orangeif
[STRING_SIZE
];
25 char enablered
[STRING_SIZE
] = "off";
26 char enableblue
[STRING_SIZE
] = "off";
27 char enableorange
[STRING_SIZE
] = "off";
30 char OVPNINPUT
[STRING_SIZE
] = "OVPNINPUT";
31 char OVPNBLOCK
[STRING_SIZE
] = "OVPNBLOCK";
32 char OVPNNAT
[STRING_SIZE
] = "OVPNNAT";
33 char WRAPPERVERSION
[STRING_SIZE
] = "ipfire-2.2.4";
35 struct connection_struct
{
36 char name
[STRING_SIZE
];
37 char type
[STRING_SIZE
];
38 char proto
[STRING_SIZE
];
39 char status
[STRING_SIZE
];
40 char local_subnet
[STRING_SIZE
];
41 char transfer_subnet
[STRING_SIZE
];
42 char role
[STRING_SIZE
];
43 char port
[STRING_SIZE
];
44 struct connection_struct
*next
;
47 typedef struct connection_struct connection
;
49 static int recursive_remove_callback(const char* fpath
, const struct stat
* sb
, int typeflag
, struct FTW
* ftwbuf
) {
50 int rv
= remove(fpath
);
57 static int recursive_remove(const char* path
) {
58 return nftw(path
, recursive_remove_callback
, 64, FTW_DEPTH
| FTW_PHYS
);
61 void exithandler(void)
72 printf("Wrapper for OpenVPN %s-debug\n", WRAPPERVERSION
);
74 printf("Wrapper for OpenVPN %s\n", WRAPPERVERSION
);
76 printf("openvpnctrl <option>\n");
77 printf(" Valid options are:\n");
78 printf(" -s --start\n");
79 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
80 printf(" -k --kill\n");
81 printf(" kills/stops OpenVPN\n");
82 printf(" -r --restart\n");
83 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
84 printf(" -sn2n --start-net-2-net\n");
85 printf(" starts all net2net connections\n");
86 printf(" you may pass a connection name to the switch to only start a specific one\n");
87 printf(" -kn2n --kill-net-2-net\n");
88 printf(" kills all net2net connections\n");
89 printf(" you may pass a connection name to the switch to only start a specific one\n");
90 printf(" -drrd --delete-rrd\n");
91 printf(" Deletes the RRD data for a specific client\n");
92 printf(" you need to pass a connection name (RW) to the switch to delete the directory (case sensitive)\n");
93 printf(" -d --display\n");
94 printf(" displays OpenVPN status to syslog\n");
95 printf(" -fwr --firewall-rules\n");
96 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
97 printf(" -sdo --start-daemon-only\n");
98 printf(" starts OpenVPN daemon only\n");
102 connection
*getConnections() {
105 if (!(fp
= fopen(CONFIG_ROOT
"/ovpn/ovpnconfig", "r"))) {
106 fprintf(stderr
, "Could not open openvpn n2n configuration file.\n");
110 char line
[STRING_SIZE
] = "";
111 char result
[STRING_SIZE
] = "";
114 connection
*conn_first
= NULL
;
115 connection
*conn_last
= NULL
;
116 connection
*conn_curr
;
118 while ((fgets(line
, STRING_SIZE
, fp
) != NULL
)) {
119 if (line
[strlen(line
) - 1] == '\n')
120 line
[strlen(line
) - 1] = '\0';
122 conn_curr
= (connection
*)malloc(sizeof(connection
));
123 memset(conn_curr
, 0, sizeof(connection
));
125 if (conn_first
== NULL
) {
126 conn_first
= conn_curr
;
128 conn_last
->next
= conn_curr
;
130 conn_last
= conn_curr
;
133 char *lineptr
= &line
;
135 if (*lineptr
== NULL
)
139 while (*lineptr
!= NULL
) {
140 if (*lineptr
== ',') {
144 *resultptr
++ = *lineptr
++;
149 strcpy(conn_curr
->status
, result
);
150 } else if (count
== 2) {
151 strcpy(conn_curr
->name
, result
);
152 } else if (count
== 4) {
153 strcpy(conn_curr
->type
, result
);
154 } else if (count
== 7) {
155 strcpy(conn_curr
->role
, result
);
156 } else if (count
== 9) {
157 strcpy(conn_curr
->local_subnet
, result
);
158 } else if (count
== 28) {
159 strcpy(conn_curr
->transfer_subnet
, result
);
160 } else if (count
== 29) {
161 strcpy(conn_curr
->proto
, result
);
162 } else if (count
== 30) {
163 strcpy(conn_curr
->port
, result
);
175 int readPidFile(const char *pidfile
) {
176 FILE *fp
= fopen(pidfile
, "r");
182 fscanf(fp
, "%d", &pid
);
188 int readExternalAddress(char* address
) {
189 FILE *fp
= fopen("/var/ipfire/red/local-ipaddress", "r");
193 int r
= fscanf(fp
, "%s", address
);
199 /* In case the read IP address is not valid, we empty
200 * the content of address and return non-zero. */
201 if (!VALID_IP(address
))
211 void ovpnInit(void) {
212 // Read OpenVPN configuration
213 kv
= initkeyvalues();
214 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings")) {
215 fprintf(stderr
, "Cannot read ovpn settings\n");
219 if (!findkey(kv
, "ENABLED", enablered
)) {
223 if (!findkey(kv
, "ENABLED_BLUE", enableblue
)){
227 if (!findkey(kv
, "ENABLED_ORANGE", enableorange
)){
232 // read interface settings
234 // details for the red int
235 memset(redif
, 0, STRING_SIZE
);
236 if ((ifacefile
= fopen(CONFIG_ROOT
"/red/iface", "r")))
238 if (fgets(redif
, STRING_SIZE
, ifacefile
))
240 if (redif
[strlen(redif
) - 1] == '\n')
241 redif
[strlen(redif
) - 1] = '\0';
246 if (!VALID_DEVICE(redif
))
248 memset(redif
, 0, STRING_SIZE
);
253 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
254 fprintf(stderr
, "Cannot read ethernet settings\n");
258 if (strcmp(enableblue
, "on") == 0) {
259 if (!findkey(kv
, "BLUE_DEV", blueif
)) {
264 if (strcmp(enableorange
, "on") == 0) {
265 if (!findkey(kv
, "ORANGE_DEV", orangeif
)) {
272 void executeCommand(char *command
) {
274 printf(strncat(command
, "\n", 2));
276 safe_system(strncat(command
, " >/dev/null 2>&1", 17));
279 void addRule(const char *chain
, const char *interface
, const char *protocol
, const char *port
) {
280 char command
[STRING_SIZE
];
282 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -i %s -p %s --dport %s -j ACCEPT",
283 chain
, interface
, protocol
, port
);
284 executeCommand(command
);
287 void flushChain(char *chain
) {
288 char str
[STRING_SIZE
];
290 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -F %s", chain
);
294 void flushChainNAT(char *chain
) {
295 char str
[STRING_SIZE
];
297 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -t nat -F %s", chain
);
301 char* calcTransferNetAddress(const connection
* conn
) {
302 char *subnetmask
= strdup(conn
->transfer_subnet
);
303 char *address
= strsep(&subnetmask
, "/");
305 if ((address
== NULL
) || (subnetmask
== NULL
)) {
309 in_addr_t _address
= inet_addr(address
);
310 in_addr_t _subnetmask
= inet_addr(subnetmask
);
311 _address
&= _subnetmask
;
313 if (strcmp(conn
->role
, "server") == 0) {
315 } else if (strcmp(conn
->role
, "client") == 0) {
321 struct in_addr address_info
;
322 address_info
.s_addr
= _address
;
324 return inet_ntoa(address_info
);
327 fprintf(stderr
, "Could not determine transfer net address: %s\n", conn
->name
);
333 char* getLocalSubnetAddress(const connection
* conn
) {
334 kv
= initkeyvalues();
335 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
336 fprintf(stderr
, "Cannot read ethernet settings\n");
340 const char *zones
[] = {"GREEN", "BLUE", "ORANGE", NULL
};
343 // Get net address of the local openvpn subnet.
344 char *subnetmask
= strdup(conn
->local_subnet
);
345 char *address
= strsep(&subnetmask
, "/");
347 if ((address
== NULL
) || (subnetmask
== NULL
)) {
351 in_addr_t _address
= inet_addr(address
);
352 in_addr_t _subnetmask
= inet_addr(subnetmask
);
354 in_addr_t _netaddr
= (_address
& _subnetmask
);
355 in_addr_t _broadcast
= (_address
| ~_subnetmask
);
357 char zone_address_key
[STRING_SIZE
];
358 char zone_address
[STRING_SIZE
];
364 snprintf(zone_address_key
, STRING_SIZE
, "%s_ADDRESS", zone
);
366 if (!findkey(kv
, zone_address_key
, zone_address
))
369 zone_addr
= inet_addr(zone_address
);
370 if ((zone_addr
> _netaddr
) && (zone_addr
< _broadcast
)) {
373 return strdup(zone_address
);
378 fprintf(stderr
, "Could not determine local subnet address: %s\n", conn
->name
);
384 void setFirewallRules(void) {
385 char command
[STRING_SIZE
];
386 char protocol
[STRING_SIZE
] = "";
387 char dport
[STRING_SIZE
] = "";
388 char dovpnip
[STRING_SIZE
] = "";
390 kv
= initkeyvalues();
391 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings"))
393 fprintf(stderr
, "Cannot read ovpn settings\n");
397 /* we got one device, so lets proceed further */
398 if (!findkey(kv
, "DDEST_PORT", dport
)){
399 fprintf(stderr
, "Cannot read DDEST_PORT\n");
403 if (!findkey(kv
, "DPROTOCOL", protocol
)){
404 fprintf(stderr
, "Cannot read DPROTOCOL\n");
408 if (!findkey(kv
, "VPN_IP", dovpnip
)){
409 fprintf(stderr
, "Cannot read VPN_IP\n");
414 flushChain(OVPNINPUT
);
415 flushChain(OVPNBLOCK
);
416 flushChainNAT(OVPNNAT
);
418 // set firewall rules
419 if (!strcmp(enablered
, "on") && strlen(redif
))
420 addRule(OVPNINPUT
, redif
, protocol
, dport
);
421 if (!strcmp(enableblue
, "on") && strlen(blueif
))
422 addRule(OVPNINPUT
, blueif
, protocol
, dport
);
423 if (!strcmp(enableorange
, "on") && strlen(orangeif
))
424 addRule(OVPNINPUT
, orangeif
, protocol
, dport
);
426 /* Allow ICMP error messages to pass. */
427 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -p icmp"
428 " -m conntrack --ctstate RELATED -j RETURN", OVPNBLOCK
);
429 executeCommand(command
);
431 // read connection configuration
432 connection
*conn
= getConnections();
434 // set firewall rules for n2n connections
435 char *local_subnet_address
= NULL
;
436 char *transfer_subnet_address
= NULL
;
437 while (conn
!= NULL
) {
438 if (strcmp(conn
->type
, "net") == 0) {
439 addRule(OVPNINPUT
, redif
, conn
->proto
, conn
->port
);
441 /* Block all communication from the transfer nets. */
442 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -s %s -j DROP",
443 OVPNBLOCK
, conn
->transfer_subnet
);
444 executeCommand(command
);
446 local_subnet_address
= getLocalSubnetAddress(conn
);
447 transfer_subnet_address
= calcTransferNetAddress(conn
);
449 if ((local_subnet_address
) && (transfer_subnet_address
)) {
450 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -t nat -A %s -s %s -j SNAT --to-source %s",
451 OVPNNAT
, transfer_subnet_address
, local_subnet_address
);
452 executeCommand(command
);
460 void stopDaemon(void) {
461 char command
[STRING_SIZE
];
463 int pid
= readPidFile("/var/run/openvpn.pid");
468 fprintf(stderr
, "Killing PID %d.\n", pid
);
471 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f /var/run/openvpn.pid");
472 executeCommand(command
);
475 void startDaemon(void) {
476 char command
[STRING_SIZE
];
478 if (!((strcmp(enablered
, "on") == 0) || (strcmp(enableblue
, "on") == 0) || (strcmp(enableorange
, "on") == 0))) {
479 fprintf(stderr
, "OpenVPN is not enabled on any interface\n");
482 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
483 executeCommand(command
);
484 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
485 executeCommand(command
);
486 snprintf(command
, STRING_SIZE
-1, "/bin/chown root.nobody /var/run/ovpnserver.log");
487 executeCommand(command
);
488 snprintf(command
, STRING_SIZE
-1, "/bin/chmod 644 /var/run/ovpnserver.log");
489 executeCommand(command
);
493 int startNet2Net(char *name
) {
494 connection
*conn
= NULL
;
495 connection
*conn_iter
;
497 conn_iter
= getConnections();
500 if ((strcmp(conn_iter
->type
, "net") == 0) && (strcmp(conn_iter
->name
, name
) == 0)) {
504 conn_iter
= conn_iter
->next
;
508 fprintf(stderr
, "Connection not found.\n");
512 if (strcmp(conn
->status
, "on") != 0) {
513 fprintf(stderr
, "Connection '%s' is not enabled.\n", conn
->name
);
517 fprintf(stderr
, "Starting connection %s...\n", conn
->name
);
519 char configfile
[STRING_SIZE
];
520 snprintf(configfile
, STRING_SIZE
- 1, CONFIG_ROOT
"/ovpn/n2nconf/%s/%s.conf",
521 conn
->name
, conn
->name
);
523 FILE *fp
= fopen(configfile
, "r");
525 fprintf(stderr
, "Could not find configuration file for connection '%s' at '%s'.\n",
526 conn
->name
, configfile
);
531 // Make sure all firewall rules are up to date.
534 // Get the external IP address.
535 char address
[STRING_SIZE
] = "";
536 int r
= readExternalAddress(address
);
538 fprintf(stderr
, "Could not read the external address\n");
542 char command
[STRING_SIZE
];
543 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
544 executeCommand(command
);
545 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --local %s --config %s", address
, configfile
);
546 executeCommand(command
);
551 int killNet2Net(char *name
) {
552 connection
*conn
= NULL
;
553 connection
*conn_iter
;
556 conn_iter
= getConnections();
559 if (strcmp(conn_iter
->name
, name
) == 0) {
563 conn_iter
= conn_iter
->next
;
567 fprintf(stderr
, "Connection not found.\n");
571 char pidfile
[STRING_SIZE
];
572 snprintf(pidfile
, STRING_SIZE
- 1, "/var/run/%sn2n.pid", conn
->name
);
574 int pid
= readPidFile(pidfile
);
576 fprintf(stderr
, "Could not read pid file of connection %s.", conn
->name
);
580 fprintf(stderr
, "Killing connection %s (PID %d)...\n", conn
->name
, pid
);
583 char command
[STRING_SIZE
];
584 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f %s", pidfile
);
585 executeCommand(command
);
587 char runfile
[STRING_SIZE
];
588 snprintf(runfile
, STRING_SIZE
- 1, "/var/run/openvpn/%s-n2n", conn
->name
);
589 rc
= recursive_remove(runfile
);
596 int deleterrd(char *name
) {
597 char rrd_dir
[STRING_SIZE
];
599 connection
*conn
= getConnections();
601 if (strcmp(conn
->name
, name
) != 0) {
606 // Handle RW connections
607 if (strcmp(conn
->type
, "host") == 0) {
608 snprintf(rrd_dir
, STRING_SIZE
- 1, "/var/log/rrd/collectd/localhost/openvpn-%s/", name
);
610 // Handle N2N connections
611 } else if (strcmp(conn
->type
, "net") == 0) {
612 snprintf(rrd_dir
, STRING_SIZE
- 1, "/var/log/rrd/collectd/localhost/openvpn-%s-n2n/", name
);
614 // Unhandled connection type
620 return recursive_remove(rrd_dir
);
626 void startAllNet2Net() {
627 int exitcode
= 0, _exitcode
= 0;
629 connection
*conn
= getConnections();
632 /* Skip all connections that are not of type "net" or disabled. */
633 if ((strcmp(conn
->type
, "net") != 0) || (strcmp(conn
->status
, "on") != 0)) {
638 _exitcode
= startNet2Net(conn
->name
);
641 if (_exitcode
> exitcode
) {
642 exitcode
= _exitcode
;
649 void killAllNet2Net() {
650 int exitcode
= 0, _exitcode
= 0;
652 connection
*conn
= getConnections();
655 /* Skip all connections that are not of type "net". */
656 if (strcmp(conn
->type
, "net") != 0) {
661 _exitcode
= killNet2Net(conn
->name
);
664 if (_exitcode
> exitcode
) {
665 exitcode
= _exitcode
;
672 void displayopenvpn(void) {
673 char command
[STRING_SIZE
];
675 snprintf(command
, STRING_SIZE
- 1, "/bin/killall -sSIGUSR2 openvpn");
676 executeCommand(command
);
679 int main(int argc
, char *argv
[]) {
688 if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
689 startNet2Net(argv
[2]);
692 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
693 killNet2Net(argv
[2]);
696 else if( (strcmp(argv
[1], "-drrd") == 0) || (strcmp(argv
[1], "--delete-rrd") == 0) ) {
705 if( (strcmp(argv
[1], "-k") == 0) || (strcmp(argv
[1], "--kill") == 0) ) {
709 else if( (strcmp(argv
[1], "-d") == 0) || (strcmp(argv
[1], "--display") == 0) ) {
716 if( (strcmp(argv
[1], "-s") == 0) || (strcmp(argv
[1], "--start") == 0) ) {
721 else if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
725 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
729 else if( (strcmp(argv
[1], "-sdo") == 0) || (strcmp(argv
[1], "--start-daemon-only") == 0) ) {
733 else if( (strcmp(argv
[1], "-r") == 0) || (strcmp(argv
[1], "--restart") == 0) ) {
739 else if( (strcmp(argv
[1], "-fwr") == 0) || (strcmp(argv
[1], "--firewall-rules") == 0) ) {