Is a custom service possible?
-
I'm trying to create a custom service, but I'm getting some errors and don't know if what I'm trying to do is possible with the way pfSense uses rc scripts/services.
I have this rc.d script "dnscrypt-proxy" in
/usr/local/etc/rc.d/
#!/bin/sh . /etc/rc.subr name=dnscrypt-proxy rcvar=dnscrypt-proxy_enable command="/usr/local/bin/${name}" pidfile="/var/run/${name}.pid" load_rc_config "${name}" : ${dnscrypt-proxy_enable="YES"} : ${dnscrypt-proxy_conf="/usr/local/etc/dnscrypt-proxy/${name}.toml"} : ${dnsmasq_restart="YES"} command_args="-config $dnscrypt-proxy_conf -pidfile $pidfile" required_files="${dnscrypt-proxy_conf}" run_rc_command "$1"
but I'm encountering errors like this when using
service
:[2.4.5-RELEASE][admin@pfSense.local]/usr/local/etc/rc.d: service dnscrypt-proxy start /usr/local/etc/rc.d/dnscrypt-proxy: WARNING: $dnscrypt-proxy_enable is not set properly - see rc.conf(5). Cannot 'start' dnscrypt-proxy. Set dnscrypt-proxy_enable to YES in /etc/rc.conf or use 'onestart' instead of 'start'.
Is there a way to make a custom service like I'm trying to do? My goal is to be able to start/stop/restart dnscrypt without having to reboot pfSense completely. I can can put a simple script in
/usr/local/etc/rc.d/
to start dnscrypt proxy successfully on boot, but I'm hoping for a more elegant solution where it can be stopped/started/restarted on the fly if I make config changes or it hangs, etc.Thanks for your help!
-
If I comment out the
rcvar
line I get a different error:#!/bin/sh . /etc/rc.subr name=dnscrypt-proxy #rcvar=dnscrypt-proxy_enable command="/usr/local/bin/${name}" pidfile="/var/run/${name}.pid" load_rc_config "${name}" : ${dnscrypt-proxy_enable="YES"} : ${dnscrypt-proxy_conf="/usr/local/etc/dnscrypt-proxy/${name}.toml"} : ${dnsmasq_restart="YES"} command_args="-config $dnscrypt-proxy_conf -pidfile $pidfile" required_files="${dnscrypt-proxy_conf}" run_rc_command "$1"
Error:
[2.4.5-RELEASE][admin@pfSense.local]/usr/local/etc/rc.d: service dnscrypt-proxy start /usr/local/etc/rc.d/dnscrypt-proxy: WARNING: run_rc_command: cannot run -proxy_program
-
pfSense doesn't use the FreeBSD RC system. You would need to create a file like packages do, for example pfBlocker:
#!/bin/sh # This file was automatically generated # by the pfSense service handler. rc_start() { # Check if DNSBL is enabled dnsblcheck="$(/usr/local/sbin/read_xml_tag.sh string installedpackages/pfblockerngdnsblsettings/config/pfb_dnsbl)" if [ "${dnsblcheck}" != 'on' ]; then exit fi # Ensure all processes are stopped rc_stop # Start DNSBL Lighttpd webserver (Unbound/Python mode) and DNSBL HTTPS Daemon (Unbound mode only) if [ -e '/var/unbound/pfb_dnsbl_lighty.conf' ]; then /usr/bin/logger -p daemon.info -t lighttpd_pfb "[pfBlockerNG] DNSBL Webserver started" /usr/local/sbin/lighttpd_pfb -f /var/unbound/pfb_dnsbl_lighty.conf fi # Check if Unbound mode is enabled unbound_mode="$(/usr/local/sbin/read_xml_tag.sh string installedpackages/pfblockerngdnsblsettings/config/dnsbl_mode)" # Start DNSBL Resolver queries Daemon if [ "${unbound_mode}" == 'dnsbl_unbound' ]; then /usr/local/bin/php -f /usr/local/pkg/pfblockerng/pfblockerng.inc queries & fi } rc_stop() { # Terminate DNSBL Lighttpd webserver, if found pidnum="$(/bin/pgrep lighttpd_pfb)" if [ ! -z "${pidnum}" ]; then /usr/bin/killall lighttpd_pfb fi # Terminate DNSBL queries Daemon, if found pidnum="$(/bin/ps -wax | /usr/bin/grep '[p]fblockerng.inc queries' | /usr/bin/awk '{print $1}')" if [ ! -z "${pidnum}" ]; then for i in ${pidnum}; do /bin/kill -9 "${i}" done fi } case $1 in start) rc_start ;; stop) rc_stop ;; restart) rc_stop rc_start ;; esac
If you want it to appear as a service in the GUI it will need a service section in the config like:
<service> <name>pfb_dnsbl</name> <rcfile>pfb_dnsbl.sh</rcfile> <executable>lighttpd_pfb</executable> <description><![CDATA[pfBlockerNG DNSBL service]]></description> </service>
Steve
-
Thanks for the helpful pointers. I managed to get it to work with this
dnscrypt-proxy.sh
script placed in/usr/local/etc/rc.d
:#!/bin/sh name="dnscrypt-proxy" conf="/usr/local/etc/dnscrypt-proxy/${name}.toml" command="/usr/local/bin/${name}" pidfile="/var/run/${name}.pid" rc_start() { # Check if DNSCrypt is enabled # dnscryptcheck="$(/usr/bin/grep '<pfb_dnsbl>' /conf/config.xml)" # if [ -z "${dnscryptcheck}" ]; then # exit # fi # Make sure all process are stopped rc_stop # Start DNSCrypt if [ -f "$conf" ]; then "${command}" -config "${conf}" -pidfile "${pidfile}" & pidnum="$(/bin/pgrep $name)" if [ -n "${pidnum}" ]; then echo "DNSCrypt started (${pidnum})" /usr/bin/logger -p daemon.info -t dnscrypt-proxy "DNSCrypt started" else echo "DNSCrypt failed to start" /usr/bin/logger -p daemon.info -t dnscrypt-proxy "DNSCrypt failed to start" fi else echo "ERROR: $conf does not exist!" /usr/bin/logger -p daemon.info -t dnscrypt-proxy "DNSCrypt failed to start - config file does not exist!" exit 1 fi } rc_stop() { # Terminate DNSCrypt process if found pidnum="$(/bin/pgrep $name)" if [ -n "${pidnum}" ]; then /usr/bin/killall $name echo "DNSCrypt stopped (${pidnum})" /usr/bin/logger -p daemon.info -t dnscrypt-proxy "DNSCrypt stopped" fi } rc_status() { # Check status and print pid if running pidnum="$(/bin/pgrep $name)" if [ -n "${pidnum}" ]; then echo "DNSCrypt is running (${pidnum})" else echo "DNSCrypt is not running" fi } if [ $# -eq 0 ]; then echo "no parameter specified - starting DNScrypt" rc_start exit fi case $1 in start) rc_start ;; stop) rc_stop ;; restart) rc_stop rc_start ;; status) rc_status ;; esac
I added these lines to the conf file:
<service> <name>dnscrypt</name> <rcfile>dnscrypt-proxy.sh</rcfile> <executable>dnscrypt-proxy</executable> <description><![CDATA[DNS Service]]></description> </service>
Couldn't figure out what the
/usr/bin/grep '<pfb_dnsbl>' /conf/config.xml
lines were for or how it would relate to my service so I commented them out.I'm sure there could be further enhancements for the GUI integration (enabling/disabling/config files) but this will do for now.
The service now starts on boot and can be restarted/started from the terminal or the UI.
Hopefully this helps anybody else trying to do the same thing.
-
@stephenw10 Perhaps it would be an idea to provide some sort of a "dummy package" with instructions how to create a pfSense package (that could even be submitted via push to netgate or simply used inhouse only) that can be cleanly installed/uninstalled and has some/most hooks/handlers as examples? I don't find the packaging and creation that simple myself so often go the way of small scripts deployed via Filer/Shellcmd pks, but some would perhaps be nice as small simple packages (e.g. custom backup packages for nextcloud or sftp tartgets or the like)?
Just a proposal :)
-
It would probably be possible to do that and someone could write up something.
However we generally discourage people from adding random services to the firewall as it can cause all sorts of issues.
This would have to be something meant for package development rather than making it easier to run custom services on a one-off basis.Steve
-
@stephenw10 said in Is a custom service possible?:
This would have to be something meant for package development rather than making it easier to run custom services on a one-off basis.
Indeed, that's what I intend as the main purpose. Examples for that would be an Icinga Daemon package (similar to the NRPE package), various Backup solutions (SFTP, GIT based, etc.) that would all spring to my mind that we already did with workarounds like custom scripts and filer/shellcmd help but that would be helpful for all so if it would be easier to start the packaging process and get to know/see the hooks where one could link into pfsense's logic (like config hooks etc.) I think we'd have a chance to get quite a few contributions of really useful packages for all :)
-
@baketopher When you say you "added these lines to conf file", which one? The global pfSense conf?
-
This one : /conf/config.xml