8 #include <netinet/in.h>
12 #include "libsmooth.h"
17 struct keyvalue
*kv
= NULL
;
18 FILE *ifacefile
= NULL
;
20 char redif
[STRING_SIZE
];
21 char blueif
[STRING_SIZE
];
22 char orangeif
[STRING_SIZE
];
23 char enablered
[STRING_SIZE
] = "off";
24 char enableblue
[STRING_SIZE
] = "off";
25 char enableorange
[STRING_SIZE
] = "off";
28 char OVPNINPUT
[STRING_SIZE
] = "OVPNINPUT";
29 char OVPNBLOCK
[STRING_SIZE
] = "OVPNBLOCK";
30 char OVPNNAT
[STRING_SIZE
] = "OVPNNAT";
31 char WRAPPERVERSION
[STRING_SIZE
] = "ipfire-2.2.4";
33 struct connection_struct
{
34 char name
[STRING_SIZE
];
35 char type
[STRING_SIZE
];
36 char proto
[STRING_SIZE
];
37 char status
[STRING_SIZE
];
38 char local_subnet
[STRING_SIZE
];
39 char transfer_subnet
[STRING_SIZE
];
40 char role
[STRING_SIZE
];
41 char port
[STRING_SIZE
];
42 struct connection_struct
*next
;
45 typedef struct connection_struct connection
;
47 void exithandler(void)
58 printf("Wrapper for OpenVPN %s-debug\n", WRAPPERVERSION
);
60 printf("Wrapper for OpenVPN %s\n", WRAPPERVERSION
);
62 printf("openvpnctrl <option>\n");
63 printf(" Valid options are:\n");
64 printf(" -s --start\n");
65 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
66 printf(" -k --kill\n");
67 printf(" kills/stops OpenVPN\n");
68 printf(" -r --restart\n");
69 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
70 printf(" -sn2n --start-net-2-net\n");
71 printf(" starts all net2net connections\n");
72 printf(" you may pass a connection name to the switch to only start a specific one\n");
73 printf(" -kn2n --kill-net-2-net\n");
74 printf(" kills all net2net connections\n");
75 printf(" you may pass a connection name to the switch to only start a specific one\n");
76 printf(" -drrd --delete-rrd\n");
77 printf(" Deletes the RRD data for a specific client\n");
78 printf(" you need to pass a connection name (RW) to the switch to delete the directory (case sensitive)\n");
79 printf(" -d --display\n");
80 printf(" displays OpenVPN status to syslog\n");
81 printf(" -fwr --firewall-rules\n");
82 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
83 printf(" -sdo --start-daemon-only\n");
84 printf(" starts OpenVPN daemon only\n");
88 connection
*getConnections() {
91 if (!(fp
= fopen(CONFIG_ROOT
"/ovpn/ovpnconfig", "r"))) {
92 fprintf(stderr
, "Could not open openvpn n2n configuration file.\n");
96 char line
[STRING_SIZE
] = "";
97 char result
[STRING_SIZE
] = "";
100 connection
*conn_first
= NULL
;
101 connection
*conn_last
= NULL
;
102 connection
*conn_curr
;
104 while ((fgets(line
, STRING_SIZE
, fp
) != NULL
)) {
105 if (line
[strlen(line
) - 1] == '\n')
106 line
[strlen(line
) - 1] = '\0';
108 conn_curr
= (connection
*)malloc(sizeof(connection
));
109 memset(conn_curr
, 0, sizeof(connection
));
111 if (conn_first
== NULL
) {
112 conn_first
= conn_curr
;
114 conn_last
->next
= conn_curr
;
116 conn_last
= conn_curr
;
119 char *lineptr
= &line
;
121 if (*lineptr
== NULL
)
125 while (*lineptr
!= NULL
) {
126 if (*lineptr
== ',') {
130 *resultptr
++ = *lineptr
++;
135 strcpy(conn_curr
->status
, result
);
136 } else if (count
== 2) {
137 strcpy(conn_curr
->name
, result
);
138 } else if (count
== 4) {
139 strcpy(conn_curr
->type
, result
);
140 } else if (count
== 7) {
141 strcpy(conn_curr
->role
, result
);
142 } else if (count
== 9) {
143 strcpy(conn_curr
->local_subnet
, result
);
144 } else if (count
== 28) {
145 strcpy(conn_curr
->transfer_subnet
, result
);
146 } else if (count
== 29) {
147 strcpy(conn_curr
->proto
, result
);
148 } else if (count
== 30) {
149 strcpy(conn_curr
->port
, result
);
161 int readPidFile(const char *pidfile
) {
162 FILE *fp
= fopen(pidfile
, "r");
168 fscanf(fp
, "%d", &pid
);
174 int readExternalAddress(char* address
) {
175 FILE *fp
= fopen("/var/ipfire/red/local-ipaddress", "r");
179 int r
= fscanf(fp
, "%s", address
);
185 /* In case the read IP address is not valid, we empty
186 * the content of address and return non-zero. */
187 if (!VALID_IP(address
))
197 void ovpnInit(void) {
198 // Read OpenVPN configuration
199 kv
= initkeyvalues();
200 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings")) {
201 fprintf(stderr
, "Cannot read ovpn settings\n");
205 if (!findkey(kv
, "ENABLED", enablered
)) {
209 if (!findkey(kv
, "ENABLED_BLUE", enableblue
)){
213 if (!findkey(kv
, "ENABLED_ORANGE", enableorange
)){
218 // read interface settings
220 // details for the red int
221 memset(redif
, 0, STRING_SIZE
);
222 if ((ifacefile
= fopen(CONFIG_ROOT
"/red/iface", "r")))
224 if (fgets(redif
, STRING_SIZE
, ifacefile
))
226 if (redif
[strlen(redif
) - 1] == '\n')
227 redif
[strlen(redif
) - 1] = '\0';
232 if (!VALID_DEVICE(redif
))
234 memset(redif
, 0, STRING_SIZE
);
239 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
240 fprintf(stderr
, "Cannot read ethernet settings\n");
244 if (strcmp(enableblue
, "on") == 0) {
245 if (!findkey(kv
, "BLUE_DEV", blueif
)) {
250 if (strcmp(enableorange
, "on") == 0) {
251 if (!findkey(kv
, "ORANGE_DEV", orangeif
)) {
258 void executeCommand(char *command
) {
260 printf(strncat(command
, "\n", 2));
262 safe_system(strncat(command
, " >/dev/null 2>&1", 17));
265 void addRule(const char *chain
, const char *interface
, const char *protocol
, const char *port
) {
266 char command
[STRING_SIZE
];
268 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -i %s -p %s --dport %s -j ACCEPT",
269 chain
, interface
, protocol
, port
);
270 executeCommand(command
);
273 void flushChain(char *chain
) {
274 char str
[STRING_SIZE
];
276 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -F %s", chain
);
280 void flushChainNAT(char *chain
) {
281 char str
[STRING_SIZE
];
283 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -t nat -F %s", chain
);
287 char* calcTransferNetAddress(const connection
* conn
) {
288 char *subnetmask
= strdup(conn
->transfer_subnet
);
289 char *address
= strsep(&subnetmask
, "/");
291 if ((address
== NULL
) || (subnetmask
== NULL
)) {
295 in_addr_t _address
= inet_addr(address
);
296 in_addr_t _subnetmask
= inet_addr(subnetmask
);
297 _address
&= _subnetmask
;
299 if (strcmp(conn
->role
, "server") == 0) {
301 } else if (strcmp(conn
->role
, "client") == 0) {
307 struct in_addr address_info
;
308 address_info
.s_addr
= _address
;
310 return inet_ntoa(address_info
);
313 fprintf(stderr
, "Could not determine transfer net address: %s\n", conn
->name
);
319 char* getLocalSubnetAddress(const connection
* conn
) {
320 kv
= initkeyvalues();
321 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
322 fprintf(stderr
, "Cannot read ethernet settings\n");
326 const char *zones
[] = {"GREEN", "BLUE", "ORANGE", NULL
};
329 // Get net address of the local openvpn subnet.
330 char *subnetmask
= strdup(conn
->local_subnet
);
331 char *address
= strsep(&subnetmask
, "/");
333 if ((address
== NULL
) || (subnetmask
== NULL
)) {
337 in_addr_t _address
= inet_addr(address
);
338 in_addr_t _subnetmask
= inet_addr(subnetmask
);
340 in_addr_t _netaddr
= (_address
& _subnetmask
);
341 in_addr_t _broadcast
= (_address
| ~_subnetmask
);
343 char zone_address_key
[STRING_SIZE
];
344 char zone_address
[STRING_SIZE
];
350 snprintf(zone_address_key
, STRING_SIZE
, "%s_ADDRESS", zone
);
352 if (!findkey(kv
, zone_address_key
, zone_address
))
355 zone_addr
= inet_addr(zone_address
);
356 if ((zone_addr
> _netaddr
) && (zone_addr
< _broadcast
)) {
359 return strdup(zone_address
);
364 fprintf(stderr
, "Could not determine local subnet address: %s\n", conn
->name
);
370 void setFirewallRules(void) {
371 char command
[STRING_SIZE
];
372 char protocol
[STRING_SIZE
] = "";
373 char dport
[STRING_SIZE
] = "";
374 char dovpnip
[STRING_SIZE
] = "";
376 kv
= initkeyvalues();
377 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings"))
379 fprintf(stderr
, "Cannot read ovpn settings\n");
383 /* we got one device, so lets proceed further */
384 if (!findkey(kv
, "DDEST_PORT", dport
)){
385 fprintf(stderr
, "Cannot read DDEST_PORT\n");
389 if (!findkey(kv
, "DPROTOCOL", protocol
)){
390 fprintf(stderr
, "Cannot read DPROTOCOL\n");
394 if (!findkey(kv
, "VPN_IP", dovpnip
)){
395 fprintf(stderr
, "Cannot read VPN_IP\n");
400 flushChain(OVPNINPUT
);
401 flushChain(OVPNBLOCK
);
402 flushChainNAT(OVPNNAT
);
404 // set firewall rules
405 if (!strcmp(enablered
, "on") && strlen(redif
))
406 addRule(OVPNINPUT
, redif
, protocol
, dport
);
407 if (!strcmp(enableblue
, "on") && strlen(blueif
))
408 addRule(OVPNINPUT
, blueif
, protocol
, dport
);
409 if (!strcmp(enableorange
, "on") && strlen(orangeif
))
410 addRule(OVPNINPUT
, orangeif
, protocol
, dport
);
412 /* Allow ICMP error messages to pass. */
413 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -p icmp"
414 " -m conntrack --ctstate RELATED -j RETURN", OVPNBLOCK
);
415 executeCommand(command
);
417 // read connection configuration
418 connection
*conn
= getConnections();
420 // set firewall rules for n2n connections
421 char *local_subnet_address
= NULL
;
422 char *transfer_subnet_address
= NULL
;
423 while (conn
!= NULL
) {
424 if (strcmp(conn
->type
, "net") == 0) {
425 addRule(OVPNINPUT
, redif
, conn
->proto
, conn
->port
);
427 /* Block all communication from the transfer nets. */
428 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -s %s -j DROP",
429 OVPNBLOCK
, conn
->transfer_subnet
);
430 executeCommand(command
);
432 local_subnet_address
= getLocalSubnetAddress(conn
);
433 transfer_subnet_address
= calcTransferNetAddress(conn
);
435 if ((local_subnet_address
) && (transfer_subnet_address
)) {
436 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -t nat -A %s -s %s -j SNAT --to-source %s",
437 OVPNNAT
, transfer_subnet_address
, local_subnet_address
);
438 executeCommand(command
);
446 void stopDaemon(void) {
447 char command
[STRING_SIZE
];
449 int pid
= readPidFile("/var/run/openvpn.pid");
454 fprintf(stderr
, "Killing PID %d.\n", pid
);
457 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f /var/run/openvpn.pid");
458 executeCommand(command
);
461 void startDaemon(void) {
462 char command
[STRING_SIZE
];
464 if (!((strcmp(enablered
, "on") == 0) || (strcmp(enableblue
, "on") == 0) || (strcmp(enableorange
, "on") == 0))) {
465 fprintf(stderr
, "OpenVPN is not enabled on any interface\n");
468 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
469 executeCommand(command
);
470 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
471 executeCommand(command
);
472 snprintf(command
, STRING_SIZE
-1, "/bin/chown root.nobody /var/run/ovpnserver.log");
473 executeCommand(command
);
474 snprintf(command
, STRING_SIZE
-1, "/bin/chmod 644 /var/run/ovpnserver.log");
475 executeCommand(command
);
479 int startNet2Net(char *name
) {
480 connection
*conn
= NULL
;
481 connection
*conn_iter
;
483 conn_iter
= getConnections();
486 if ((strcmp(conn_iter
->type
, "net") == 0) && (strcmp(conn_iter
->name
, name
) == 0)) {
490 conn_iter
= conn_iter
->next
;
494 fprintf(stderr
, "Connection not found.\n");
498 if (strcmp(conn
->status
, "on") != 0) {
499 fprintf(stderr
, "Connection '%s' is not enabled.\n", conn
->name
);
503 fprintf(stderr
, "Starting connection %s...\n", conn
->name
);
505 char configfile
[STRING_SIZE
];
506 snprintf(configfile
, STRING_SIZE
- 1, CONFIG_ROOT
"/ovpn/n2nconf/%s/%s.conf",
507 conn
->name
, conn
->name
);
509 FILE *fp
= fopen(configfile
, "r");
511 fprintf(stderr
, "Could not find configuration file for connection '%s' at '%s'.\n",
512 conn
->name
, configfile
);
517 // Make sure all firewall rules are up to date.
520 // Get the external IP address.
521 char address
[STRING_SIZE
] = "";
522 int r
= readExternalAddress(address
);
524 fprintf(stderr
, "Could not read the external address\n");
528 char command
[STRING_SIZE
];
529 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
530 executeCommand(command
);
531 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --local %s --config %s", address
, configfile
);
532 executeCommand(command
);
537 int killNet2Net(char *name
) {
538 connection
*conn
= NULL
;
539 connection
*conn_iter
;
541 conn_iter
= getConnections();
544 if (strcmp(conn_iter
->name
, name
) == 0) {
548 conn_iter
= conn_iter
->next
;
552 fprintf(stderr
, "Connection not found.\n");
556 char pidfile
[STRING_SIZE
];
557 snprintf(pidfile
, STRING_SIZE
- 1, "/var/run/%sn2n.pid", conn
->name
);
559 int pid
= readPidFile(pidfile
);
561 fprintf(stderr
, "Could not read pid file of connection %s.", conn
->name
);
565 fprintf(stderr
, "Killing connection %s (PID %d)...\n", conn
->name
, pid
);
568 char command
[STRING_SIZE
];
569 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f %s", pidfile
);
570 executeCommand(command
);
575 int deleterrd(char *name
) {
576 connection
*conn
= getConnections();
578 char rrd_file
[STRING_SIZE
];
579 snprintf(rrd_file
, STRING_SIZE
- 1, "/var/log/rrd/collectd/localhost/openvpn-%s/if_octets.rrd", name
);
581 char rrd_dir
[STRING_SIZE
];
582 snprintf(rrd_dir
, STRING_SIZE
- 1, "/var/log/rrd/collectd/localhost/openvpn-%s", name
);
585 /* Find only RW-Connections with the given name. */
586 if (((strcmp(conn
->type
, "host") == 0) && (strcmp(conn
->name
, name
) == 0))) {
597 void startAllNet2Net() {
598 int exitcode
= 0, _exitcode
= 0;
600 connection
*conn
= getConnections();
603 /* Skip all connections that are not of type "net" or disabled. */
604 if ((strcmp(conn
->type
, "net") != 0) || (strcmp(conn
->status
, "on") != 0)) {
609 _exitcode
= startNet2Net(conn
->name
);
612 if (_exitcode
> exitcode
) {
613 exitcode
= _exitcode
;
620 void killAllNet2Net() {
621 int exitcode
= 0, _exitcode
= 0;
623 connection
*conn
= getConnections();
626 /* Skip all connections that are not of type "net". */
627 if (strcmp(conn
->type
, "net") != 0) {
632 _exitcode
= killNet2Net(conn
->name
);
635 if (_exitcode
> exitcode
) {
636 exitcode
= _exitcode
;
643 void displayopenvpn(void) {
644 char command
[STRING_SIZE
];
646 snprintf(command
, STRING_SIZE
- 1, "/bin/killall -sSIGUSR2 openvpn");
647 executeCommand(command
);
650 int main(int argc
, char *argv
[]) {
659 if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
660 startNet2Net(argv
[2]);
663 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
664 killNet2Net(argv
[2]);
667 else if( (strcmp(argv
[1], "-drrd") == 0) || (strcmp(argv
[1], "--delete-rrd") == 0) ) {
676 if( (strcmp(argv
[1], "-k") == 0) || (strcmp(argv
[1], "--kill") == 0) ) {
680 else if( (strcmp(argv
[1], "-d") == 0) || (strcmp(argv
[1], "--display") == 0) ) {
687 if( (strcmp(argv
[1], "-s") == 0) || (strcmp(argv
[1], "--start") == 0) ) {
692 else if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
696 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
700 else if( (strcmp(argv
[1], "-sdo") == 0) || (strcmp(argv
[1], "--start-daemon-only") == 0) ) {
704 else if( (strcmp(argv
[1], "-r") == 0) || (strcmp(argv
[1], "--restart") == 0) ) {
710 else if( (strcmp(argv
[1], "-fwr") == 0) || (strcmp(argv
[1], "--firewall-rules") == 0) ) {